gpt4 book ai didi

c++ - 按值捕获 shared_ptr 的 lambda 如何影响它的 use_count()?

转载 作者:搜寻专家 更新时间:2023-10-31 02:02:57 24 4
gpt4 key购买 nike

我很好奇 shared_ptr 在 lambda 中被值捕获时的生命周期。

我原以为只要 lambda 仍在内存中,它的 use_count() 就始终 >= 1,但我的测试显示出一些意外情况:使用计数降为 0,然后递增到 1在 lambda 体内...

这是我测试过的:

  1. 创建一个 shared_ptr
  2. 定义一个按值捕获 shared_ptr 的 lambda
  3. 重置shared_ptr
  4. 运行 lambda

在第 3 阶段,shared_ptr 的 use_count() 降为 0 - 但对象未被销毁。在第 4 阶段 - 在 lambda 内部 - use_count() 回到 1。lambda 运行后,use_count() 回到 0,但对象没有被销毁直到 lambda 被销毁。

我想知道这是怎么/为什么会这样?

use_count() 不应该在 lambda 定义之后为 2,然后在 lambda 内部为 1?


testing code on Repl.it:

#include <iostream>
#include <memory>

class Foo {
public:
Foo( int v = 0 ) : val(v) {}
~Foo(){
std::cout << "--- Foo destroyed ---" << std::endl;
}
int val = 0;
};

void logPtr( const std::shared_ptr<Foo>& p ){
std::cout << "ptr: refs = " << p.use_count();
if (p) {
std::cout << ", val = " << p->val << std::endl;
}
else {
std::cout << ", nullptr" << std::endl;
}
}

int main() {

std::shared_ptr<Foo> ptr = std::make_shared<Foo>( 0 );

logPtr(ptr);

std::cout << "--- define lambda ---\n";

auto lambda = [=]() {

std::cout << "--- run lambda ---\n";
if (ptr) { ptr->val++; }
logPtr(ptr);
std::cout << "--- end lambda ---\n";

};

logPtr(ptr);

std::cout << "--- reset ptr ---\n";
ptr.reset();
logPtr(ptr);

// run lambda
lambda();
logPtr(ptr);

}

这是输出:

ptr: refs = 1, val = 0
--- define lambda ---
ptr: refs = 2, val = 0
--- reset ptr ---
ptr: refs = 0, nullptr
--- run lambda ---
ptr: refs = 1, val = 1
--- end lambda ---
ptr: refs = 0, nullptr
--- Foo destroyed ---

最佳答案

Shouldn't use_count() be 2 after the lambda definition

它是:

--- define lambda ---
ptr: refs = 2, val = 0

and then 1 inside the lambda?

它是:

--- run lambda ---
ptr: refs = 1, val = 1

您感到困惑的部分与 lambda 无关。您可以通过创建共享指针的简单拷贝来产生相同的效果:

  std::shared_ptr<Foo> ptr = std::make_shared<Foo>( 0 );

logPtr( ptr );

std::cout << "--- define lambda ---\n";

auto cpy = ptr;

logPtr(ptr);

std::cout << "--- reset ptr ---\n";
ptr.reset();

logPtr(ptr);

// run "lambda"
{
std::cout << "--- run lambda ---\n";
if (cpy) {
cpy->val++;
}
logPtr( cpy );
std::cout << "--- end lambda ---\n";
}

logPtr( ptr );

您似乎缺少的是 reset() 的语义。作为cppreference explains , 它

Releases the ownership of the managed object, if any.

这意味着

If *this already owns an object and it is the last shared_ptr owning it, the object is destroyed through the owned deleter.

在您的代码中,最初有两个共享指针,共享引用对象的所有权。

ptr.reset() 之后,第一个指针不再是所有者。它重置回 null/0。但是,第二个指针(lambda 中的拷贝)仍然是所有者并使引用的对象保持事件状态(现在 use_count 为 1)。

您的其余代码只是检查两个不同的指针:一个仍然拥有该对象,另一个不拥有任何东西。

使用原始指针的等效代码如下所示:

Foo *ptr = new Foo(0);
Foo *cpy = ptr; // create a copy
ptr = null; // "reset" the first pointer
logPtr(cpy); // examine the copy
delete cpy; // release the object through the last active pointer

关于c++ - 按值捕获 shared_ptr 的 lambda 如何影响它的 use_count()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56279664/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com