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

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

为什么 C++ 采用自由函数:

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

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

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

?

最佳答案

TL;DR:静态成员函数始终可以访问私有(private)数据,但自由函数只有在明确标记为 friend 时才能访问私有(private)数据。选择将这些函数实现为自由函数(有一小部分实现为友元函数)不是随机的历史产物,而是一个经过深思熟虑的决定,以改进封装,同时为所有 std 提供一致的命名方案::make_x 函数。


many standard factory functions在 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

对于上述所有情况,仅使用 x 的公共(public)接口(interface)即可正确实现 make_x 函数。在 make_sharedmake_exception_ptr 的情况下,最有效的实现需要访问 std::shared_ptr 的内部数据std::exception_ptr。所有其他都可以仅使用公共(public)接口(interface)来实现,性能损失为零。

将这些函数实现为非友元自由函数可以减少访问对象私有(private)内部的代码量(a desirable property,因为当更少的代码可以访问私有(private)数据时,需要访问的地方就会减少对违反对象不变量的操作进行审计,并且在对象内部发生变化时可能需要更改的地方更少)。

如果 make_shared 是唯一类似的工厂函数,将其作为成员函数可能是有意义的,但由于大多数此类函数不需要是 friend 函数高效运行,make_shared 也实现为自由函数,以保持一致性。

这是正确的设计,好像静态成员 make 函数一直被使用,那么除了 make_sharedmake_exception_ptr 之外的所有情况,成员函数不可避免地会过度访问 x 对象的私有(private)数据。通过标准化设计,少量需要访问私有(private)数据的make_x函数可以标记为friend,其余的则默认正确封装。如果在某些情况下使用非成员 make_x 而在其他情况下使用静态成员 make,标准库将变得不一致并且更难学习。

关于c++ - 为什么 std::make_unique 而不是 std::unique_ptr::make?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42922749/

相关文章:

c++ - 使用 Clang 编译 Boost 时出错

c++ - ROS 移动约束

C++:重构管理命名空间

c++ - 连续枚举C++ 11

c++ - scoped_ptr 所有权

c++ - 避免对非虚拟析构函数进行对象切片

c++ - 将清除共享智能指针上的调用重置

c++ - 如何将文件写入 OS X 应用程序资源文件夹?

c++ - 输出 UTF-8 (u8) std::string

c++ - 有没有办法检测混合类型和非类型的任意模板类?