为什么 make_unique 和 make_shared 使用括号而不是大括号?
Why make_unique and make_shared uses parenthesis and not curly braces?
即标准库的所有实现(在 MSVC、clang、gcc 中)都使用以下代码(为便于阅读而简化):
template<class T, class... Args>
inline unique_ptr<T> make_unique(Args&&... args)
{
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
但是为什么不用大括号呢?即:
template<class T, class... Args>
inline unique_ptr<T> make_unique(Args&&... args)
{
return unique_ptr<T>(new T{std::forward<Args>(args)...});
// ^ here and ^ here
}
(make_shared
的相同问题。)
因为花括号会根据 T
是什么以及它定义的构造函数来做不同的事情。
如果 T
有一个构造函数接受 std::initializer_list
参数,那么在使用大括号时将调用该构造函数。这不是真正的目的。
因为这两种实现在某些情况下会有不同的行为。标准库必须选择其中一种语义使其保持一致。
#include <memory>
#include <vector>
#include <iostream>
template<class T, class... Args>
inline std::unique_ptr<T> my_make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T{std::forward<Args>(args)...});
}
int main() {
auto a = std::make_unique<std::vector<int>>(12);
std::cout << a->size() << "\n";
auto b = my_make_unique<std::vector<int>>(12);
std::cout << b->size() << "\n";
}
这里a
是12号的vector
,b
是1号的vector
,值为12。
即标准库的所有实现(在 MSVC、clang、gcc 中)都使用以下代码(为便于阅读而简化):
template<class T, class... Args>
inline unique_ptr<T> make_unique(Args&&... args)
{
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
但是为什么不用大括号呢?即:
template<class T, class... Args>
inline unique_ptr<T> make_unique(Args&&... args)
{
return unique_ptr<T>(new T{std::forward<Args>(args)...});
// ^ here and ^ here
}
(make_shared
的相同问题。)
因为花括号会根据 T
是什么以及它定义的构造函数来做不同的事情。
如果 T
有一个构造函数接受 std::initializer_list
参数,那么在使用大括号时将调用该构造函数。这不是真正的目的。
因为这两种实现在某些情况下会有不同的行为。标准库必须选择其中一种语义使其保持一致。
#include <memory>
#include <vector>
#include <iostream>
template<class T, class... Args>
inline std::unique_ptr<T> my_make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T{std::forward<Args>(args)...});
}
int main() {
auto a = std::make_unique<std::vector<int>>(12);
std::cout << a->size() << "\n";
auto b = my_make_unique<std::vector<int>>(12);
std::cout << b->size() << "\n";
}
这里a
是12号的vector
,b
是1号的vector
,值为12。