gpt4 book ai didi

c++:MSVC vs. GCC+CLANG:处理捕获类成员变量的 lambdas,正确的方法是什么?

转载 作者:太空狗 更新时间:2023-10-29 23:11:01 25 4
gpt4 key购买 nike

考虑以下看起来非常无辜的代码段:

#include <functional>
#include <iostream>
#include <list>
#include <memory>

struct foo;

std::list<std::weak_ptr<foo>> wptrs;
std::function<void()> global_func;

struct foo {
int &a;
foo(int &a) : a{ a } { }
~foo() {
global_func = [&] {
wptrs.remove_if([](auto &x) { return x.expired(); });
std::cout << "a= " << a << std::endl;
};
}
};

int main() {
int a = 5;
auto ptr = std::make_shared<foo>(a);
wptrs.emplace_back(ptr);
ptr = nullptr; // object is destroyed here
global_func();
return 0;
}

当我第一次在 MSVC (Visual Studio 2017) 上遇到这个问题时,我正在一个 TCP/IP 服务器上工作,它试图清理 weak_ptr 的列表。 s 到连接对象。连接对象安排一个 lambda 来清除 weak_ptr 的列表通过调用 weak_ptr<T>::expired() 的连接数.我以前很高兴,因为在使用 clang-6.0+ 或 g++-7+ 编译时,一切都可以正常工作。然后,我不得不使用 MSVC,并在调用 destruct 时收到读取访问冲突。我很震惊,并试图生成一个展示相同问题的最小示例。上面给出了最小的例子。

最小的示例使错误消息清晰明了,似乎 MSVC lambda 试图访问 this->__this->a .此访问顺序表明 MSVC 未捕获地址 a (或对 a 的引用),而是捕获 *this 的地址并获得对 a 的访问权限使用这个对象。自 *this当弱引用计数变为零时,对象被完全释放,我有一个内存访问错误。

显然,MSVC 方法与 g++ 和 clang 的方法截然不同。那么,我的问题是哪个编译器是正确的?

附言MSVC 案例的简单修复:

#include <functional>
#include <iostream>
#include <list>
#include <memory>

struct foo;

std::list<std::weak_ptr<foo>> wptrs;
std::function<void()> global_func;

struct foo {
int &a;
foo(int &a) : a{ a } { }
~foo() {
global_func = [a = &a] { // capture a ptr instead
wptrs.remove_if([](auto &x) { return x.expired(); });
std::cout << "a= " << *a << std::endl;
};
}
};

int main() {
int a = 5;
auto ptr = std::make_shared<foo>(a);
wptrs.emplace_back(ptr);
ptr = nullptr; // object is destroyed here
global_func();
return 0;
}

最佳答案

*this 的成员从未被捕获:他们can’t be explicitly captured ,并使用它们 implicitly captures *this (通过引用,不管 capture-default ;为清楚起见,请考虑使用 [=,this])。所以你的第二个例子是唯一正确的方法; GCC 和 Clang 可能一直在优化 foo::a 的使用,因为引用不能被反弹。

关于c++:MSVC vs. GCC+CLANG:处理捕获类成员变量的 lambdas,正确的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52709883/

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