为什么可以在unique_ptr的向量中放置两次指针?

不应该std::unique_ptr防止出现这种错误的可能性吗?

#include <iostream>
#include <vector>
#include <memory>

struct B {
    int b;
};

int main()
{
    std::vector<std::unique_ptr<B>> v;  // unique_ptr can be stored in a container
    B* p = new B;
    v.emplace_back(p);
    std::cout << "p:" <<p <<"n";
    std::cout << "v[0]:"<<v[0].get() << "n";
    v.emplace_back(p);
    std::cout << "p:" <<p <<"n";
    std::cout << "v[1]:"<<v[1].get() << "n";

}

检测到双重释放时的错误信息:

*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001094c20 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f3da200b7e5]
...
======= Memory map: ========
00400000-00402000 r-xp 00000000 ca:01 3228321                            /tmp/1617748074.6996937/a.out
...             

忽略双重释放时的输出:

p:0x1094c20
v[0]:0x1094c20
p:0x1094c20
v[1]:0x1094c20

回答

std::unique_ptr 如果使用得当,可以防止双重免费错误:

  • 永远不要创建一个拥有的原始指针;使用std::make_unique.
  • 如果您必须绝对创建一个拥有的原始指针 using new(为了从工厂函数调用私有构造函数),则在立即将原始指针包装在 a 中std::unique_ptr并且不执行任何其他操作的语句中
    执行此操作,例如 return std::unique_ptr<Base>(new Derived(...));
  • 不要std::unique_ptr在任何其他上下文中使用采用原始指针的构造函数。

如果遵循这些准则,每个人都unique_ptr将管理一个不受其他任何人管理的对象。如果不遵循它们,则可能会出现像您观察到的那样的错误,其中unique_ptr可以从同一个原始指针创建多个实例。两个实例都不“知道”您传递给它的原始指针已经被另一个实例拥有。如果unique_ptr构造函数必须检查是否有其他人拥有该指针,则会为每个用户带来性能开销。我们使用 C++ 来避免这种不必要的开销。只要您遵循准则,就没有必要。


以上是为什么可以在unique_ptr的向量中放置两次指针?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>