Visual C++: MSVC vs. GCC+CLANG: 处理 lambda 捕获类成员变量,正确的方法是什么?
visual c++: MSVC vs. GCC+CLANG: Handling lambdas capturing class member variables, what is the correct approach?
考虑以下看起来非常无辜的代码段:
#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
列表。连接对象调度 lambda 以通过调用weak_ptr<T>::expired()
来清除weak_ptr
连接的列表。我之前很高兴,因为使用 clang-6.0+ 或 g++-7+ 编译时一切都可以正常工作。然后,我不得不使用 MSVC,并在调用析构时收到读取访问冲突。我很震惊,并试图生成一个显示相同问题的最小示例。上面给出了最小的例子。
最小的示例使错误消息清晰,似乎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
的成员永远不会被捕获:它们不能被显式捕获,并且隐式使用它们会捕获*this
(通过引用而不考虑捕获默认值;为清楚起见,请考虑使用[=,this]
(。 所以你的第二个例子是唯一正确的方法;GCC 和 Clang 可能一直在优化foo::a
的使用,因为引用无法反弹。
相关文章:
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 枚举环境变量的惯用C++14/C++17方法
- 绑定派生类方法C++从实例范围之外的分隔 std::function 变量调用
- 是否可以依赖函数范围的静态变量来执行程序关闭期间调用的方法?
- 从私有成员变量的成员方法返回unique_ptr
- 在派生类中使用基类的私有成员变量的最佳方法
- 打印所有继承的类成员变量和方法
- C++方法中的引用变量
- Visual C++: MSVC vs. GCC+CLANG: 处理 lambda 捕获类成员变量,正确的方法是什么?
- 有没有一种通用的方法来实现不变量
- 有没有将变量名称转换为双指针的简短方法?
- C++:将向量传递到构造函数以创建成员变量的最佳方法?
- C++中变量混叠的最佳方法
- 比较C++变量的最有效方法
- 使用类在C++中存储和列出变量/方法是否是一种好的做法
- 存储变量的更有效方法是什么?
- 对具有相同方法的不同类使用一个变量
- 如何使用另一个变量访问对象的变量/方法
- C++,静态局部变量(方法)与全局(文件)变量有什么区别
- Awesomium允许我在JS中调用/使用c++变量/方法吗?