问题描述
以以下代码片段为例:
template <typename FOO>
std::shared_ptr<FOO> createSharedPtr(bool yesNo) {
if (!yesNo) {
return nullptr;
} else {
return make_shared<FOO>();
}
}
我认为上面的 return nullptr;
语句符合 C++ 11 标准,因为 nullptr
将用于在返回调用者时构造 null
std::shared_ptr
,如cppreference shared_ptr 描述:
constexpr shared_ptr( std::nullptr_t ) noexcept; (2)
然而,我的一位同事一直坚持他应该选择 return shared_ptr<FOO>();
,因为他找不到任何官方文档或示例将 nullptr
分配给 std::shared_ptr
。
我的理解正确吗?如果是,我应该给他看什么文件来证明我的意见?
更新 1
实际上我确实与他进行了讨论,引用了 cppreference shared_ptr,并且他现在的关注点似乎是:
这意味着使用 shared_ptr() 或 shared_ptr(nullptr)。 但是返回 nullptr 需要进行从 nullptr 到 shared_ptr 的转换,并且需要一个复制构造函数。
如果我理解正确,他关心的是如何将 nullptr
构造为 shared_ptr
。关于这一点,关键是从nullptr
到shared_ptr
的隐式转换。这应该相当于:
class A {
public:
A(int a) : a_(a) {}
private:
int a_;
};
A a = 1;
我应该看哪个文档来说明上面代码的正确性?
更新 2
看起来 Converting constructor 可以解释这里的关键点。谢谢大家!
解决方法
他们的意思是一样的。在这里您甚至可以看到生成的汇编代码是相同的:https://godbolt.org/z/odKc4q9ja
如果您喜欢简洁和/或不喜欢 nullptr
,您可以 return {}
以获得相同的效果。
您的同事似乎将 std::shared_ptr<Foo>(nullptr)
与 std::shared_ptr<FOO>(static_cast<FOO*>(nullptr))
混淆。你是对的:提到的重载已经保证返回的 shared_ptr
不包含资源。
但即使是 std::shared_ptr<FOO>(static_cast<FOO*>(nullptr))
也是安全的。从标准来看,ctor的前提条件:
前提条件:表达式delete[] p,当T是数组类型时,或delete p,当T不是数组类型时,行为定义良好,不抛出异常。
delete static_cast<FOO*>(nullptr)
满足两个条件:它什么都不做。