繁体   English   中英

C++ std::shared_ptr 调试断言失败

[英]C++ std::shared_ptr debug assertion failure

我正在使用 Visual Studio 2019 研究 std::share_pointer,我编写了一个程序来实现交换两个整数。

#include <iostream>
#include <memory>

void swap0(int* a, int* b)
{
    int t = *a;
    *a = *b;
    *b = t;
}

void swap1(std::shared_ptr<int> a, std::shared_ptr<int> b)
{
    int t = *a;
    *a = *b;
    *b = t;
}

int main()
{
    int a = 10;
    int b = 20;
    std::cout << a << " " << b << std::endl; // 10 20
    std::shared_ptr<int> pa(&a);
    std::shared_ptr<int> pb(&b);
    swap1(pa, pb);
    std::cout << a << " " << b << std::endl; // 10 20
}

但该程序显示了一个名为 Microsoft Visual C++ Runtime Library 的对话框。 这是对话框的信息。

Debug Assertion Failed!
Program:
....../ConsoleApplication1.exe
File: minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp
Line: 904

Express: _CrtIsValidHeapPointer(block)

......

然后我用MinGW尝试了相同的代码,程序运行正常。 我滥用了 shared_ptr 吗?

您的问题出在这一行,共享指针要求它使用的数据分配在堆上,而不是堆栈上。 这就是构造函数采用指针而不是引用的原因。

//...
std::shared_ptr<int> pa(new int{a});
std::shared_ptr<int> pb(new int{b});
//...

请注意,在 swap1 中,您交换的是 shared_ptrs 中包含的整数,而不是 shared_ptrs 本身。

一般来说,使用 std::swap 交换东西效果更好。

//...
int a = 0;
int b = 5;
std::swap(a, b); //values of a and b are swapped, no need to roll your own swap functions

这甚至可以用来交换 shared_ptrs,注意这与交换它们的内容不同。

//...
std::shared_ptr<int> a(new int{0});
std::shared_ptr<int> b(new int{5});
std::swap(*a, *b); //swap contents of shared pointers
std::swap(a, b); //swap the shared pointers

是的,你滥用了它。

shared_ptr很有用,因为它会在必要时自动删除它拥有的 object。 这是它的唯一目的。 在这里,您尝试使用指向局部变量的指针创建shared_ptr ,然后 object 将尝试删除它。 除非你真的不能这样做,因为变量在堆栈上(尝试在main的末尾调用delete &a ,你会得到相同的结果)。

通常,您将使用std::make_shared创建一个shared_ptr 这样,原始指针根本不必通过您的手指向 go。

这篇文章建议谨慎使用相同的原始指针初始化共享指针(也不要使用原始指针变量直接初始化 class)。 我建议std::make_shared因为它是制作这些的标准方法。 要解决该错误,您可以按如下方式初始化 pa 和 pb:

std::shared_ptr<int> pa = std::make_shared<int>(a);
std::shared_ptr<int> pb = std::make_shared<int>(b);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM