我正在使用代码库,该代码库广泛使用以下语法:
shared_ptr<Object> myObject = (shared_ptr<Object>) new Object();
我注意到我无法使用make_shared
访问私有构造函数,但shared_ptr<Object> myObject = (shared_ptr<Object>) new Object();
工作得很好。我应该只是因为它似乎有效吗?有危险吗?它与make_shared
有什么不同?
我知道this问题中的答案,该问题对make_shared
和:
std::shared_ptr<Object> p2(new Object("foo"));
但我还没有找到我遇到的语法的参考。它是不同的,还是与上面相同?
答案 0 :(得分:10)
make_shared
在与控制块相同的内存块中分配对象。这样可以提高缓存一致性并减少分配。
允许make_shared
执行此操作的一种方法是在您的类中使用私有令牌,以及使用该令牌的公共构造函数。
class Object {
private:
struct token_t{ private: token_t() {}; friend class Object; };
static token_t token() { return {}; }
Object() = default;
public:
Object( token_t ):Object() {}
};
现在我们可以make_shared<Object>( Object::token() )
。
这给了我们一个分配,并没有违反构造的隐私,因为只有访问Object
私有字段的东西才能调用该构造函数。但是,它们可以将令牌传递给另一个函数(如make_shared
),然后它可以调用相关的构造函数。这自然适用于更多的论据。
至于你的语法:
std::shared_ptr<Object> myObject = (std::shared_ptr<Object>) new Object();
(std::shared_ptr<Object>) new Object();
只是从shared_ptr<Object>
明确构建new Object()
。它相当于std::shared_ptr<Object>(new Object)
。
然后我们接受这个prvalue并从中构造myObject
。在C ++ 03 11和14中,这种复制/移动结构被省略了。在C ++ 17中,prvalue&#34;构造指令&#34;直接应用于myObject
。在实践中,这导致相同的机器代码(除非你是一个傻瓜,并明确告诉你的编译器不要忽视构造)。
简而言之,它有效。唯一的缺点是从Object
分配中重复分配单独的控制块。