C++ 如何在C++;11兰巴?
有时,我们对捕获对象状态的lambda的生存期一无所知(例如,从对象返回它,将它注册为回调,但不能取消订阅等)。如何确保lambda在调用时不会访问已经销毁的对象C++ 如何在C++;11兰巴?,c++,c++11,lambda,shared-ptr,weak-ptr,C++,C++11,Lambda,Shared Ptr,Weak Ptr,有时,我们对捕获对象状态的lambda的生存期一无所知(例如,从对象返回它,将它注册为回调,但不能取消订阅等)。如何确保lambda在调用时不会访问已经销毁的对象 #include <iostream> #include <memory> #include <string> class Foo { public: Foo(const std::string& i_name) : name(i_name) {} std::functi
#include <iostream>
#include <memory>
#include <string>
class Foo {
public:
Foo(const std::string& i_name) : name(i_name) {}
std::function<void()> GetPrinter() {
return [this]() {
std::cout << name << std::endl;
};
}
std::string name;
};
int main() {
std::function<void()> f;
{
auto foo = std::make_shared<Foo>("OK");
f = foo->GetPrinter();
}
auto foo = std::make_shared<Foo>("WRONG");
f();
return 0;
}
#包括
#包括
#包括
福班{
公众:
Foo(const std::string&i_name):name(i_name){}
std::函数GetPrinter(){
返回[此](){
std::无法延长对象生存期
lambda可以捕获指向此
的共享指针,因此当至少存在一个lambda时,对象不会死亡
class Foo : public std::enable_shared_from_this<Foo> {
public:
Foo(const std::string& i_name) : name(i_name) {}
std::function<void()> GetPrinter() {
std::shared_ptr<Foo> that = shared_from_this();
return [that]() {
std::cout << that->name << std::endl;
};
}
std::string name;
};
用法示例
class Foo {
public:
Foo(const std::string& i_name) : name(i_name) {}
std::function<void()> GetPrinter() {
auto monitor = tracker.get_monitor();
return [this, monitor]() {
if (!monitor.alive()) {
std::cout << "The object is already dead" << std::endl;
return;
}
std::cout << this->name << std::endl;
};
}
private:
lifetime_tracker tracker;
std::string name;
};
class-Foo{
公众:
Foo(const std::string&i_name):name(i_name){}
std::函数GetPrinter(){
自动监视器=跟踪器。获取监视器();
返回[此,监视器](){
如果(!monitor.alive()){
std::coutStas的答案是好的,当您可以确定对象由共享的\u ptr
管理时,但这并不总是可能的。不过,您始终可以做的是跟踪对象的生存期,并在lambda中添加断言
void ignore(void *) { }
class Foo {
public:
Foo(const std::string& i_name) : name(i_name) {}
Foo(const Foo& other) : name(other.name) {}
Foo(Foo&& other) : name(std::move(other.name)) {}
Foo& operator=(Foo other) { swap(*this, other); return *this; }
friend void swap(Foo& a, Foo& b) { using std::swap; swap(a.name, b.name); }
std::function<void()> GetPrinter() {
std::weak_ptr<void> monitor = this->monitor;
return [=]() {
assert (!monitor.expired());
std::cout << name << std::endl;
};
}
std::string name;
private:
std::shared_ptr<void> monitor{this, ignore};
};
void忽略(void*){}
福班{
公众:
Foo(const std::string&i_name):name(i_name){}
Foo(constfoo&other):name(other.name){}
Foo(Foo&&other):名称(std::move(other.name)){}
Foo&operator=(Foo-other){swap(*this,other);返回*this;}
朋友无效交换(Foo&a,Foo&b){使用std::swap;交换(a.name,b.name);}
std::函数GetPrinter(){
std::weak_ptr monitor=此->监视器;
返回[=](){
断言(!monitor.expired());
std::难道@P0W-hmm不接受该代码,可能clang已经过时了吗?我想clang-3.3应该编译这个(现在不能检查)。是的,在最新的一个上是这样的,谢谢!是的,好主意。但是您需要定义复制构造函数。现在,如果您复制Foo对象,它将表现不正确。@Stas Right,谢谢您指出这一点。还有一个移动构造函数和赋值运算符。
class Foo {
public:
Foo(const std::string& i_name) : name(i_name) {}
std::function<void()> GetPrinter() {
auto monitor = tracker.get_monitor();
return [this, monitor]() {
if (!monitor.alive()) {
std::cout << "The object is already dead" << std::endl;
return;
}
std::cout << this->name << std::endl;
};
}
private:
lifetime_tracker tracker;
std::string name;
};
void ignore(void *) { }
class Foo {
public:
Foo(const std::string& i_name) : name(i_name) {}
Foo(const Foo& other) : name(other.name) {}
Foo(Foo&& other) : name(std::move(other.name)) {}
Foo& operator=(Foo other) { swap(*this, other); return *this; }
friend void swap(Foo& a, Foo& b) { using std::swap; swap(a.name, b.name); }
std::function<void()> GetPrinter() {
std::weak_ptr<void> monitor = this->monitor;
return [=]() {
assert (!monitor.expired());
std::cout << name << std::endl;
};
}
std::string name;
private:
std::shared_ptr<void> monitor{this, ignore};
};