我应该使用shared_ptr <Object> myObject =(shared_ptr <Object>)new Object()来访问私有构造函数吗?

nik*_*aza 7 c++ constructor shared-ptr c++11

我正在使用代码库,它广泛使用以下语法:

shared_ptr<Object> myObject = (shared_ptr<Object>) new Object();
Run Code Online (Sandbox Code Playgroud)

我注意到我无法访问私有构造函数make_shared,但shared_ptr<Object> myObject = (shared_ptr<Object>) new Object();工作得很好.我应该使用它只是因为它似乎工作?有危险吗?它有什么不同make_shared

我知道这个问题的答案,它在make_shared和之间进行了比较:

std::shared_ptr<Object> p2(new Object("foo"));
Run Code Online (Sandbox Code Playgroud)

但是我找不到对我遇到的语法的引用.它是不同的,还是与上面相同?

Yak*_*ont 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() {}
};
Run Code Online (Sandbox Code Playgroud)

现在我们可以make_shared<Object>( Object::token() ).

这给了我们一个分配,并没有违反构造的隐私,因为只有访问私有字段的东西Object才能调用该构造函数.但是,它们可以将令牌传递给另一个函数(如make_shared),然后它可以调用相关的构造函数.这自然适用于更多的论点.

至于你的语法:

std::shared_ptr<Object> myObject = (std::shared_ptr<Object>) new Object();
Run Code Online (Sandbox Code Playgroud)

(std::shared_ptr<Object>) new Object();只需显式构造一个shared_ptr<Object>from new Object().它相当于std::shared_ptr<Object>(new Object).

然后我们采用这个prvalue并myObject从中构造.在C++ 03 11和14中,这种复制/移动结构被省略了.在C++ 17中,prvalue"构造指令"直接应用于myObject.在实践中,这会产生相同的机器代码(除非你是一个傻瓜,并明确告诉你的编译器不要忽视构造).

简而言之,它有效.唯一的缺点是分配的单独控制块的双重Object分配.

  • @alexis的一点是,make shared只能在一个上下文中使用一个令牌来调用,你可以从该类访问私有数据(或者通过代理向他们授予oermission,从这个上下文传递一个令牌).如果您根本不想对其进行访问控制,只需将构造函数设为公共.即假设`static std :: shared_ptr <Class> Class :: make(){return std :: make_shared <Class>(token()); }` (2认同)