为什么std :: make_unique而不是std :: unique_ptr :: make?

vla*_*don 25 c++ smart-pointers c++14

为什么C++采用免费函数:

std::make_unique(...);
std::make_shared(...);
Run Code Online (Sandbox Code Playgroud)

而不是使用静态成员函数:

std::unique_ptr::make(...); // static
std::shared_ptr::make(...); // static
Run Code Online (Sandbox Code Playgroud)

Man*_*rse 24

TL; DR:静态成员函数始终可以访问私有数据,但是当明确标记为时,自由函数只能访问私有数据friend.将这些函数实现为自由函数(少数被实现为友元函数)的选择不是随机的历史工件,而是有意识地决定改进封装,同时为所有std::make_x函数提供一致的命名方案.


C++中有许多标准工厂函数:

std::make_pair
std::make_tuple
std::make_unique
std::make_shared //efficiency
std::make_exception_ptr //efficiency
std::make_move_iterator
std::make_reverse_iterator
std::make_error_code
std::make_error_condition
//And several more are proposed for C++17
Run Code Online (Sandbox Code Playgroud)

对于以上所有,make_x只使用公共接口可以正确实现该功能x.在的情况下,make_sharedmake_exception_ptr,最有效的实施需要获得的内部数据std::shared_ptrstd::exception_ptr.所有其他功能都可以使用公共接口实现,性能损失为零.

将这些函数实现为非朋友自由函数可以减少访问对象私有内部的代码量(这是一个理想的属性,因为当较少的代码可以访问私有数据时,需要审计的地方较少)违反对象不变量的操作,如果对象的内部发生更改,则可能需要更改的位置更少.

如果它make_shared是唯一类似的工厂函数,它可能有意义成为一个成员函数,但由于大多数此类函数不需要是friend有效运行的函数,make_shared因此也可以实现为自由函数,一致性.

这是正确的设计,就好像make一直使用静态成员函数一样,然后在除了make_shared和之外的每种情况下make_exception_ptr,成员函数都不可避免地会过度访问x对象的私有数据.使用标准化设计,make_x需要访问私有数据的少量功能可以标记为friend,其余部分默认正确封装.如果make_x在某些情况下使用非成员而在其他情况下使用静态成员make,则标准库将变得不一致并且更难以学习.

  • +1:[有效的C++项目23:首选非成员非友情函数](http://stackoverflow.com/questions/5989734/effective-c-item-23-prefer-non-member-non-friend-functions-to-member -功能).这只是封装101. (4认同)
  • 非常确定有超过4个:http://en.cppreference.com/mwiki/index.php?title = Special%3ASearch&search = make_ (2认同)

Vit*_*meo 16

一致性.

我认为没有任何令人信服的理由来使用::make语法而不是当前语法.我认为make_unique并且make_shared优先考虑静态::make函数以保持与现有的std::make_pairstd::make_heap函数一致,这是存在于C++之前的11.


请注意,它std::make_pair有一个很大的优点:它会自动从函数调用中推导出结果对的类型:

auto p0 = std::make_pair(1, 1.f); // pair<int, float>
Run Code Online (Sandbox Code Playgroud)

如果我们有std::pair::make,那么我们将不得不写:

auto p1 = std::pair<int, float>::make(1, 1.f);
Run Code Online (Sandbox Code Playgroud)

这违背了目的make_pair.


  • 因此,我认为这是因为开发人员已经习惯和类似的功能make_uniquemake_shared被选中make_pair.

  • make_pair被选中而不是pair::make前面提到的好处.

  • @DavidHaim类似事物的一致性是一个有价值的属性 (8认同)
  • @DavidHaim:由于参数推断,它在过去选择了``make_pair`可能的`pair :: make`.由于`make_pair`已经存在,`make_unique`可能*之后被*unique_ptr :: make`选中. (4认同)
  • 此外,至少部分委员会更倾向于非会员的非朋友职能而不是成员:http://www.gotw.ca/gotw/084.htm (2认同)
  • @DavidHaim如果所有内容都按照您的预期运行,它使标准库更容易学习,并且因为`std :: make_pair`已经存在,库的用户来*期望*creator函数是独立的函数,以`的std ::使_...`. (2认同)