提问人:fredoverflow 提问时间:8/12/2011 最后编辑:Xeofredoverflow 更新时间:9/5/2016 访问量:73543
make_unique完美转发
make_unique and perfect forwarding
问:
为什么标准 C++11 库中没有函数模板?我发现std::make_unique
std::unique_ptr<SomeUserDefinedType> p(new SomeUserDefinedType(1, 2, 3));
有点啰嗦。以下不是更好吗?
auto p = std::make_unique<SomeUserDefinedType>(1, 2, 3);
这很好地隐藏了类型,并且只提到了一次类型。new
无论如何,这是我实现以下目标的尝试:make_unique
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
我花了很长时间才编译这些东西,但我不确定它是否正确。是吗?这究竟是什么意思?编译器对此有何看法?std::forward
std::forward<Args>(args)...
答:
虽然没有什么能阻止你编写自己的帮助程序,但我相信在库中提供的主要原因是它实际上创建了一个与 不同的内部类型的共享指针,该指针的分配方式不同,如果没有专用的帮助程序,就无法实现这一点。make_shared<T>
shared_ptr<T>(new T)
另一方面,你的 更正:这实际上并非如此:使用函数调用来包装表达式可提供异常安全性,例如在调用函数的情况下。如果两个原始表达式彼此未排序,则意味着如果一个新表达式因异常而失败,另一个表达式可能会泄漏资源。至于为什么标准中没有:它只是被遗忘了。(这种情况偶尔会发生。标准中也没有全局,即使应该有一个。make_unique
包装器只是围绕一个新
表达的句法糖,所以虽然它可能看起来很赏心悦目,但它并没有带来任何新的东西
。new
void f(std::unique_ptr<A> &&, std::unique_ptr<B> &&)
new
make_unique
std::cbegin
另请注意,这需要第二个模板参数,您应该以某种方式允许该参数;这与 不同,后者使用类型擦除来存储自定义删除程序,而不使它们成为类型的一部分。unique_ptr
shared_ptr
评论
shared_ptr<T>(new T)
make_shared<T>()
shared_ptr
shared_ptr
make_shared
new
std::make_shared
不仅仅是 的简写。它做了一些你离不开它的事情。std::shared_ptr<Type> ptr(new Type(...));
为了完成其工作,除了为实际指针保留存储之外,还必须分配一个跟踪块。但是,由于分配了实际对象,因此有可能在同一内存块中同时分配对象和跟踪块。std::shared_ptr
std::make_shared
std::make_shared
因此,虽然将分配两个内存(一个用于跟踪块,一个在跟踪块中),但将分配一个内存块。std::shared_ptr<Type> ptr = new Type(...);
new
std::shared_ptr
std::make_shared<Type>(...)
这对 .唯一要做的就是稍微方便一点。仅此而已。std::shared_ptr
std::make_unique
评论
在 C++ 中,11 也用于“包扩展”(在模板代码中)。...
要求是将其用作包含未展开参数包的表达式的后缀,并且它只是将表达式应用于包的每个元素。
例如,在示例的基础上进行构建:
std::forward<Args>(args)... -> std::forward<int>(1), std::forward<int>(2),
std::forward<int>(3)
std::forward<Args...>(args...) -> std::forward<int, int, int>(1,2,3)
我认为后者是不正确的。
此外,参数包不能传递给未展开的函数。我不确定模板参数包。
评论
std::forward<Args>(args)...
forward<T1>(x1), forward<T2>(x2), ...
forward
C++标准化委员会主席Herb Sutter在他的博客上写道:
C++ 11 没有包含的部分是一个疏忽,几乎肯定会在未来添加。
make_unique
他还给出了一个与 OP 给出的实现相同的实现。
编辑:现在是 C++14 的一部分。std::make_unique
评论
make_unique
make_unique
make_unique
make_unique_t
make_unique
void f( int *, int* ){}
no throw
void f( int, int ) {}
typedef unique_ptr<int> up; f( *up(new int(5)), *up(new int(10)))
make_unique
(如上所述)如何不是异常安全的? (旁注:是的,我确实认为这提高了可以应用它的地方的异常安全性)make_unique
make_unique
make_unique
make_unique
make_unique
很好,但 Stephan T. Lavavej(更广为人知的是 STL)有一个更好的解决方案,它适用于数组版本。make_unique
#include <memory>
#include <type_traits>
#include <utility>
template <typename T, typename... Args>
std::unique_ptr<T> make_unique_helper(std::false_type, Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
template <typename T, typename... Args>
std::unique_ptr<T> make_unique_helper(std::true_type, Args&&... args) {
static_assert(std::extent<T>::value == 0,
"make_unique<T[N]>() is forbidden, please use make_unique<T[]>().");
typedef typename std::remove_extent<T>::type U;
return std::unique_ptr<T>(new U[sizeof...(Args)]{std::forward<Args>(args)...});
}
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return make_unique_helper<T>(std::is_array<T>(), std::forward<Args>(args)...);
}
这可以在他的核心C++ 6视频中看到。
STL的make_unique版本的更新版本现在以N3656的形式提供。这个版本被C++草案14采用。
评论
make_unique
受到 Stephan T. Lavavej 实现的启发,我认为有一个支持数组扩展的make_unique可能会很好,它在 github 上,我很想得到关于它的评论。它允许您执行以下操作:
// create unique_ptr to an array of 100 integers
auto a = make_unique<int[100]>();
// create a unique_ptr to an array of 100 integers and
// set the first three elements to 1,2,3
auto b = make_unique<int[100]>(1,2,3);
上一个:比较不同容器的迭代器
下一个:我应该返回集合还是流?
评论
unique_ptr
shared_ptr
make_unique
new
delete
make_unique
new
make_unique
std::unique_ptr
unique_ptr
auto p = make_unique<foo>(bar, baz)
std::unique_ptr<foo> p(new foo(bar, baz))
make_unique
进来了,看 isocpp.org/blog/2013/04/trip-report-iso-c-spring-2013-meetingC++14