是否std::make_unique
有像任何效率优势std::make_shared
?
与手动构建相比std::unique_ptr
:
std::make_unique<int>(1); // vs
std::unique_ptr<int>(new int(1));
Run Code Online (Sandbox Code Playgroud) 什么是使用的优势,std::make_unique
在new
运营商的初始化std::unique_ptr
?
换句话说,为什么
std::unique_ptr<SomeObject> a = std::make_unique(SomeObject(...))
Run Code Online (Sandbox Code Playgroud)
比做好
std::unique_ptr<SomeObject> a = new SomeObject(...)
Run Code Online (Sandbox Code Playgroud)
我尝试在线查看很多,我知道new
在现代C++中避免使用操作符是一个很好的经验法则,但我不确定在这个确切的场景中有什么优势.它是否可以防止可能发生的任何类型的内存泄漏?做一个std::make_unique
比使用更快new
吗?
如何为具有unique_ptr
成员变量的类实现复制构造函数?我只考虑C++ 11.
问题确实符合标题:我很想知道这种差异的技术原因是什么,还有理由?
std::shared_ptr<void> sharedToVoid; // legal;
std::unique_ptr<void> uniqueToVoid; // ill-formed;
Run Code Online (Sandbox Code Playgroud) 据我所知,引入了C++ 14 std::make_unique
,因为由于没有指定参数评估顺序,这是不安全的:
f(std::unique_ptr<MyClass>(new MyClass(param)), g()); // Syntax A
Run Code Online (Sandbox Code Playgroud)
(说明:如果评估首先为原始指针分配内存,则g()
在std::unique_ptr
构造之前抛出调用和异常,然后内存泄漏.)
呼叫std::make_unique
是一种约束呼叫顺序的方法,从而使事情变得安全:
f(std::make_unique<MyClass>(param), g()); // Syntax B
Run Code Online (Sandbox Code Playgroud)
从那以后,C++ 17澄清了评估顺序,使得Syntax A也安全,所以这里是我的问题:在C++ 17中仍然有理由使用std::make_unique
over std::unique_ptr
的构造函数吗?你能举一些例子吗?
截至目前,我能想象的唯一原因是它只允许输入MyClass
一次(假设您不需要依赖多态std::unique_ptr<Base>(new Derived(param))
).但是,这似乎是一个非常弱的原因,特别是当构造函数std::make_unique
不允许指定删除器时std::unique_ptr
.
而且为了清楚起见,我并不是主张std::make_unique
从标准库中删除(至少为了向后兼容而保持它有意义),而是想知道是否仍然存在强烈倾向于它的情况std::unique_ptr
我正在观看Chandler Carruth在CppCon 2019中的演讲:
在该示例中,他举例说明了您对使用std::unique_ptr<int>
over和会产生多少开销而感到惊讶int*
。该段大约在时间点17:25开始。
您可以看一下他的示例代码对(godbolt.org)的编译结果 -可以看到,确实,编译器似乎不愿意传递unique_ptr值-实际上,底线是只是一个地址-在寄存器内,仅在直接内存中。
Carruth先生在27:00左右提出的观点之一是,C ++ ABI要求按值传递参数(某些但不是全部;也许-非基本类型?而不是在寄存器中。
我的问题:
PS-为了不给这个问题留下代码:
普通指针:
void bar(int* ptr) noexcept;
void baz(int* ptr) noexcept;
void foo(int* ptr) noexcept {
if (*ptr > 42) {
bar(ptr);
*ptr = 42;
}
baz(ptr);
}
Run Code Online (Sandbox Code Playgroud)
唯一指针:
using std::unique_ptr;
void bar(int* ptr) noexcept;
void baz(unique_ptr<int> ptr) noexcept;
void foo(unique_ptr<int> ptr) noexcept {
if (*ptr > 42) {
bar(ptr.get());
*ptr = 42;
}
baz(std::move(ptr));
}
Run Code Online (Sandbox Code Playgroud) 难道C++ 11标准库提供任何实用程序从一个转换std::shared_ptr
到std::unique_ptr
,或反之亦然?这是安全的操作吗?
我正在尝试编译代码审查上发布的以下线程池程序来测试它.
https://codereview.stackexchange.com/questions/55100/platform-independant-thread-pool-v4
但我得到了错误
threadpool.hpp: In member function ‘std::future<decltype (task((forward<Args>)(args)...))> threadpool::enqueue_task(Func&&, Args&& ...)’:
threadpool.hpp:94:28: error: ‘make_unique’ was not declared in this scope
auto package_ptr = make_unique<task_package_impl<R, decltype(bound_task)>> (std::move(bound_task), std::move(promise));
^
threadpool.hpp:94:81: error: expected primary-expression before ‘>’ token
auto package_ptr = make_unique<task_package_impl<R, decltype(bound_task)>>(std::move(bound_task), std::move(promise));
^
main.cpp: In function ‘int main()’:
main.cpp:9:17: error: ‘make_unique’ is not a member of ‘std’
auto ptr1 = std::make_unique<unsigned>();
^
main.cpp:9:34: error: expected primary-expression before ‘unsigned’
auto ptr1 = std::make_unique<unsigned>();
^
main.cpp:14:17: error: ‘make_unique’ is not a member …
Run Code Online (Sandbox Code Playgroud) 我试着理解我是如何std::unique_ptr
工作的,并且我找到了这个文件.作者从以下示例开始:
#include <utility> //declarations of unique_ptr
using std::unique_ptr;
// default construction
unique_ptr<int> up; //creates an empty object
// initialize with an argument
unique_ptr<int> uptr (new int(3));
double *pd= new double;
unique_ptr<double> uptr2 (pd);
// overloaded * and ->
*uptr2 = 23.5;
unique_ptr<std::string> ups (new std::string("hello"));
int len=ups->size();
Run Code Online (Sandbox Code Playgroud)
令我困惑的是,在这一行
unique_ptr<int> uptr (new int(3));
Run Code Online (Sandbox Code Playgroud)
我们使用整数作为参数(在圆括号之间)和这里
unique_ptr<double> uptr2 (pd);
Run Code Online (Sandbox Code Playgroud)
我们使用指针作为参数.它有什么不同吗?
对我来说还不清楚的是,以这种方式声明的指针将如何与以"正常"方式声明的指针不同.