为什么 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_shared
和 make_exception_ptr
的情况下,最有效的实现需要访问 std::shared_ptr
或 的内部数据std::exception_ptr
。所有其他都可以仅使用公共(public)接口(interface)来实现,性能损失为零。
将这些函数实现为非友元自由函数可以减少访问对象私有(private)内部的代码量(a desirable property,因为当更少的代码可以访问私有(private)数据时,需要访问的地方就会减少对违反对象不变量的操作进行审计,并且在对象内部发生变化时可能需要更改的地方更少)。
如果 make_shared
是唯一类似的工厂函数,将其作为成员函数可能是有意义的,但由于大多数此类函数不需要是 friend
函数高效运行,make_shared
也实现为自由函数,以保持一致性。
这是正确的设计,好像静态成员 make
函数一直被使用,那么除了 make_shared
和 make_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/