您可能希望將this指針捕獲到c++ lambda中,但這將捕獲原始指針。如果需要延長對象的生命周期,則需要捕獲強引用。“捕獲對自己的強引用”的常見模式是同時捕獲強引用和原始this。強引用保持this為活的,并且使用this方便訪問成員。
概念
- 類模板 std::function 是通用多態函數包裝器。 std::function 的實例能存儲、復制及調用任何可復制構造(CopyConstructible)的可調用(Callable)目標——函數、 lambda 表達式、 bind 表達式或其他函數對象,還有指向成員函數指針和指向數據成員指針。
- std::enable_shared_from_this 能讓其一個對象(假設其名為 t ,且已被一個 std::shared_ptr 對象 pt 管理)安全地生成其他額外的 std::shared_ptr 實例(假設名為 pt1, pt2, ... ) ,它們與 pt 共享對象 t 的所有權。
例子1
您可能希望將this指針捕獲到c++ lambda中,但這將捕獲原始指針。如果需要延長對象的生命周期,則需要捕獲強引用。“捕獲對自己的強引用”的常見模式是同時捕獲強引用和原始this。強引用保持this為活的,并且使用this方便訪問成員。
#include <functional>
#include <iostream>
#include <memory>
#include <string>
std::vector<std::function<void(void)>> actions;
class Widget : public std::enable_shared_from_this<Widget> {
public:
Widget(const std::string name){name_ = name;}
void reg(){
// std::shared_ptr
auto callback = [lifetime = shared_from_this(), this]() {
action(name_);
};
actions.push_back(callback);
}
virtual void action(std::string name){
std::cout << "widget action:" << name << std::endl;
}
std::string name_;
};
class Table : public Widget {
public:
Table(const std::string name):Widget(name){}
virtual void action(std::string name){
std::cout << "table action:" << name << std::endl;
}
};
void reg_action(){
auto widget = std::make_shared<Widget>("widget");
widget->reg();
auto table = std::make_shared<Table>("table");
table->reg();
}
int main(int argc, char* argv[]){
reg_action();
for (const auto& action : actions) {
action();
}
}
輸出:
widget action:widget
table action:table

在線測試
https://wandbox.org/permlink/HDrKO6Hn6tROiVEj
例子2
#include <functional>
#include <iostream>
#include <memory>
std::vector<std::function<void(void)>> actions;
class Widget : public std::enable_shared_from_this<Widget> {
public:
void reg(){
actions.push_back(std::bind(&Widget::action, shared_from_this()));
}
virtual void action(){
std::cout << "widget action" << std::endl;
}
};
class Table : public Widget {
public:
virtual void action(){
std::cout << "table action" << std::endl;
}
};
void reg_action(){
auto widget = std::make_shared<Widget>();
widget->reg();
auto table = std::make_shared<Table>();
table->reg();
}
int main(int argc, char* argv[]){
reg_action();
for (const auto& action : actions) {
action();
}
}
輸出:
widget action
table action