为什么make_unique和make_shared使用圆括号而不是花括号?

3
即所有标准库的实现(在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。)
2个回答

6

因为这两种实现在某些情况下的行为不同。标准库必须选择其中一种语义以使其保持一致。

#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的向量b是一个大小为1的向量,其值为12。


5

花括号的作用取决于 T 是什么以及它定义了哪些构造函数。

如果 T 有一个接受 std::initializer_list 参数的构造函数,则在使用花括号时将调用该构造函数。这并不是真正想要的结果。


2
除非需要,否则您可以自己提供大括号,例如 std::make_unique<std::vector<int>>({2,3}) - aschepler
除非 {2, 3} 可以推导出来,否则它将无法编译。 - Jarod42
我相信这个答案是正确的。我记得曾经在某个讨论中读到过,当构造一个 std::vector 时使用类似这样的方法会出现问题,如果你用花括号和圆括号提供两个整数参数,则会有非常不同的结果。 - AndyG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接