在 C++ 中,make_unique 的使用如何防止内存泄漏?

How does use of make_unique prevent memory-leak, in C++?

fn(unique_ptr<A>{new A{}},unique_ptr<B>{new B{}});

很麻烦,因为 AB 如果在那里抛出异常,就会泄露。

fn(make_unique<A>(),make_unique<B>());

另一方面被认为是异常安全的。

问题:

为什么?使用make_unique如何防止内存泄漏?
make_unique 做了什么而 default unique_ptr 没有?

请帮帮我。
谢谢。

How does use of make_unique prevent memory-leak, in C++?

std::make_unique 不会“防止”内存泄漏,因为它仍然可以在使用 std::make_unique.

的程序中写入内存泄漏。

std::make_unique 是什么让编写没有内存泄漏的程序变得更容易。


A or B gets leaked if an exception is thrown there.

Why?

C++17 之前的版本:

因为如果你分配 A,然后在构造应该拥有 Astd::unique_ptr 之前调用 B 的构造函数,以及 B 的构造函数=] 抛出,然后 A 将泄漏(或者 AB 反转也会发生同样的情况)。

自 C++17 起:

没有泄漏,因为上述情况在所示示例中不会再发生。

What does make_unique do that the default unique_ptr does not?

std::make_unique 分配内存,并且要么成功 returns 一个有效的 std::unique_ptr,要么抛出异常而不泄漏内存。

std::unique_ptr(T*) 接受单独分配的指针。如果在调用构造函数之前抛出异常,那么将永远不会有拥有分配的唯一指针。


可以在不使用 std::make_unique:

的情况下修复 (pre-C++17) 错误
auto a = std::unique_ptr<A>{new A{}};
auto b = std::unique_ptr<B>{new B{}};
fn(std::move(a), std::move(b));

但是如果你一直使用std::make_unique,那么你就不会一不小心犯写漏版的错误了。此外,std::make_unique 可以让您避免编写 new,这允许您使用经验法则“为每个新写一个删除”。 0 个新 -> 0 个删除。