逐一销毁单个 shared_ptr
Destructing a Single shared_ptr One-by-One
我试图一个接一个地销毁 shared_ptr,但是当我销毁最后一个指针时,use_count() 变得疯狂。观察我的代码:
#include <iostream>
#include <memory>
int main() {
int * val = new int(5);
std::shared_ptr<int> myPtr = std::make_shared<int>(*val);
myPtr.~__shared_ptr();
}
将在调试器中产生以下输出:
myPtr value: 5 myPtr.use_count():8787448 // Or some other large int
我希望在最终销毁时它将 use_count() 设置为 0 并为整数释放内存。这似乎 none 正在发生。
我可以在 use_count() == 1 时使用 if() 语句,但这看起来很不雅。有谁知道另一种解决方案?
I am attempting to destruct a shared_ptr one-by-one,
我不知道那是什么意思,但是...
myPtr.~__shared_ptr();
永远,永远,永远不要这样做。
您是 运行 自动对象的析构函数,即存在于堆栈中并在超出范围时由编译器自动销毁的对象。通过手动销毁它,您会导致它被销毁两次。你不能结束一个对象的生命两次,它不是詹姆斯·邦德,它只有一次。
两次销毁同一个对象是未定义的行为。这意味着可能会发生奇怪的事情。询问为什么从具有未定义行为的程序中得到奇怪的结果是浪费时间。当你有未定义的行为时会发生奇怪的事情因为你有未定义的行为。任何事情都可能发生。你应该庆幸这只是奇怪,而不是灾难性的。
该标准在 12.4 [class.dtor]:
中明确指出这种情况是未定义的行为
Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the
destructor is invoked for an object whose lifetime has ended (3.8). [Example: if the destructor for an
automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily
invoke implicit destruction of the object, the behavior is undefined. — end example]
更糟糕的是,你是 运行 myPtr
的基础 class 的析构函数,所以你只破坏了对象的 部分 .这意味着你有一个对象,其中一部分是死的,一部分是活的,然后在作用域结束时,它的一部分再次被杀死。在任何情况下,这都不是正确的做法。曾经。
I was hoping on the final destruction it would set the use_count() to 0 and deallocate the memory for the integer. It appears none of this is happening.
你的结论是错误的。它可能正在发生,但如果对象被销毁并且内存被释放,那么试图查看它会产生无意义的结果。你不能问僵尸它的名字是什么,它会回答 "BRAINZZZZ!" 而不是告诉你任何有用的东西。并吃掉你的大脑。现在你死了。不要玩丧尸
此外,正如 Neil Kirk 上面评论的那样,这也是错误的:
int * val = new int(5);
std::shared_ptr<int> myPtr = std::make_shared<int>(*val);
您在堆上创建一个 int
,然后在将由 shared_ptr
管理的堆上创建它的 副本。 shared_ptr
拥有一个 int
,它与 *val
具有相同的值,但没有任何东西拥有 val
,因此这将是内存泄漏。您可能打算这样做:
int * val = new int(5);
std::shared_ptr<int> myPtr(val);
或更可能是:
int val = 5;
std::shared_ptr<int> myPtr = std::make_shared<int>(val);
我想我明白你想要什么了。您想检测共享对象的使用计数何时为零。
这样做的方法是使用 std::weak_ptr that is designed to work with the std::shared_ptr 这样您就可以跟踪对象是否已被销毁。
这里:
#include <memory>
#include <iomanip>
#include <iostream>
int main()
{
// weak_ptr is only convertable to a shared_ptr if the shared_ptr
// usage count is > 0
std::weak_ptr<int> wp;
{
std::shared_ptr<int> ptr = std::make_shared<int>(5);
wp = ptr; // link weak_ptr to shared_ptr
if(auto sp = wp.lock()) // try to convert weak_ptr to shared_ptr
{
// if we get here use_count was > 0
std::cout << "Before: use count > 0: "
<< std::boolalpha << (sp.use_count() > 0) << '\n';
}
else
{
// if we get here use_count was == 0
std::cout << "Before: Destroyed\n";
}
// ptr goes out of scope here
}
if(auto sp = wp.lock()) // try to convert weak_ptr to shared_ptr
{
// if we get here use_count was > 0
std::cout << "After: use count > 0: "
<< std::boolalpha << (sp.use_count() > 0) << '\n';
}
else
{
// if we get here use_count was == 0
std::cout << "After: Destroyed\n";
}
}
基本上,如果链接 std::shared_ptr still holds a reference to the object then the associated std::weak_ptr can be converted to a std::shared_ptr using std::weak_ptr::lock. If that fails then the associated std::shared_ptr 不再指向共享对象 - 它已被销毁。
我试图一个接一个地销毁 shared_ptr,但是当我销毁最后一个指针时,use_count() 变得疯狂。观察我的代码:
#include <iostream>
#include <memory>
int main() {
int * val = new int(5);
std::shared_ptr<int> myPtr = std::make_shared<int>(*val);
myPtr.~__shared_ptr();
}
将在调试器中产生以下输出:
myPtr value: 5 myPtr.use_count():8787448 // Or some other large int
我希望在最终销毁时它将 use_count() 设置为 0 并为整数释放内存。这似乎 none 正在发生。
我可以在 use_count() == 1 时使用 if() 语句,但这看起来很不雅。有谁知道另一种解决方案?
I am attempting to destruct a shared_ptr one-by-one,
我不知道那是什么意思,但是...
myPtr.~__shared_ptr();
永远,永远,永远不要这样做。
您是 运行 自动对象的析构函数,即存在于堆栈中并在超出范围时由编译器自动销毁的对象。通过手动销毁它,您会导致它被销毁两次。你不能结束一个对象的生命两次,它不是詹姆斯·邦德,它只有一次。
两次销毁同一个对象是未定义的行为。这意味着可能会发生奇怪的事情。询问为什么从具有未定义行为的程序中得到奇怪的结果是浪费时间。当你有未定义的行为时会发生奇怪的事情因为你有未定义的行为。任何事情都可能发生。你应该庆幸这只是奇怪,而不是灾难性的。
该标准在 12.4 [class.dtor]:
中明确指出这种情况是未定义的行为Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended (3.8). [Example: if the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined. — end example]
更糟糕的是,你是 运行 myPtr
的基础 class 的析构函数,所以你只破坏了对象的 部分 .这意味着你有一个对象,其中一部分是死的,一部分是活的,然后在作用域结束时,它的一部分再次被杀死。在任何情况下,这都不是正确的做法。曾经。
I was hoping on the final destruction it would set the use_count() to 0 and deallocate the memory for the integer. It appears none of this is happening.
你的结论是错误的。它可能正在发生,但如果对象被销毁并且内存被释放,那么试图查看它会产生无意义的结果。你不能问僵尸它的名字是什么,它会回答 "BRAINZZZZ!" 而不是告诉你任何有用的东西。并吃掉你的大脑。现在你死了。不要玩丧尸
此外,正如 Neil Kirk 上面评论的那样,这也是错误的:
int * val = new int(5);
std::shared_ptr<int> myPtr = std::make_shared<int>(*val);
您在堆上创建一个 int
,然后在将由 shared_ptr
管理的堆上创建它的 副本。 shared_ptr
拥有一个 int
,它与 *val
具有相同的值,但没有任何东西拥有 val
,因此这将是内存泄漏。您可能打算这样做:
int * val = new int(5);
std::shared_ptr<int> myPtr(val);
或更可能是:
int val = 5;
std::shared_ptr<int> myPtr = std::make_shared<int>(val);
我想我明白你想要什么了。您想检测共享对象的使用计数何时为零。
这样做的方法是使用 std::weak_ptr that is designed to work with the std::shared_ptr 这样您就可以跟踪对象是否已被销毁。
这里:
#include <memory>
#include <iomanip>
#include <iostream>
int main()
{
// weak_ptr is only convertable to a shared_ptr if the shared_ptr
// usage count is > 0
std::weak_ptr<int> wp;
{
std::shared_ptr<int> ptr = std::make_shared<int>(5);
wp = ptr; // link weak_ptr to shared_ptr
if(auto sp = wp.lock()) // try to convert weak_ptr to shared_ptr
{
// if we get here use_count was > 0
std::cout << "Before: use count > 0: "
<< std::boolalpha << (sp.use_count() > 0) << '\n';
}
else
{
// if we get here use_count was == 0
std::cout << "Before: Destroyed\n";
}
// ptr goes out of scope here
}
if(auto sp = wp.lock()) // try to convert weak_ptr to shared_ptr
{
// if we get here use_count was > 0
std::cout << "After: use count > 0: "
<< std::boolalpha << (sp.use_count() > 0) << '\n';
}
else
{
// if we get here use_count was == 0
std::cout << "After: Destroyed\n";
}
}
基本上,如果链接 std::shared_ptr still holds a reference to the object then the associated std::weak_ptr can be converted to a std::shared_ptr using std::weak_ptr::lock. If that fails then the associated std::shared_ptr 不再指向共享对象 - 它已被销毁。