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

时间:2017-03-21 09:17:03

标签: c++ c++14 smart-pointers

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

std::make_unique(...);
std::make_shared(...);

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

std::unique_ptr::make(...); // static
std::shared_ptr::make(...); // static

3 个答案:

答案 0 :(得分:24)

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

C ++中有many standard factory functions

std::make_x

对于上述所有内容,只能使用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 的公共接口正确实现make_x功能。对于xmake_shared,最有效的实施方式需要访问make_exception_ptrstd::shared_ptr的内部数据。所有其他功能都可以使用公共接口实现,而且性能损失为零。

将这些函数实现为非朋友自由函数可以减少访问对象私有内部的代码量(a desirable property),因为当较少的代码可以访问私有数据时,可以减少访问私有数据的位置。必须对违反对象不变量的操作进行审计,如果对象内部发生更改,则可能需要更改的位置更少。

如果std::exception_ptr是唯一类似的工厂函数,它可能是成员函数,但由于大多数此类函数不需要make_shared函数来有效运行,为了保持一致性,friend也作为自由函数实现。

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

答案 1 :(得分:17)

<强>一致性

我不认为有任何令人信服的理由使用::make语法而不是当前语法。我假设make_uniquemake_shared首选静态::make函数,以保持与现有的std::make_pairstd::make_heap函数一致,这些函数存在于C +之前11。

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

auto p0 = std::make_pair(1, 1.f); // pair<int, float>

如果我们有std::pair::make,那么我们必须写:

auto p1 = std::pair<int, float>::make(1, 1.f);

这违背了make_pair的目的。

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

  • make_pair被选中而不是pair::make以获得上述好处。

答案 2 :(得分:3)

除了惯例之外,没有具体的理由 - 静态类函数可以完成全局函数可以执行的所有操作(功能明智) C ++更喜欢包含在已定义的命名空间内的全局函数(用于实用程序函数) 其他编程语言(如Java)更喜欢静态公共函数,因为不支持全局函数。

这对make_***来说并不陌生,其他例子存在:

std::this_thread::XXXX而不是std::thread::XXXX_current尽管将与当前执行线程相关的函数作为静态函数放在thread类中可能有意义,但它们是全局的在this_thread命名空间内。

另外,我们可以使用std::container::sort这样的std::container是容器的辅助类,但我们改为std::sort