C++代码赏析:回调中对象保活

开发 前端
您可能希望将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


责任编辑:武晓燕 来源: 今日头条
相关推荐

2010-02-04 16:07:39

C++回调函数

2023-01-03 13:30:14

C++代码map

2022-10-24 08:03:04

MySQL数据库

2010-01-21 10:23:53

C++代码

2011-06-15 11:05:14

C语言回调函数

2009-08-12 10:11:18

C# 回调函数

2009-08-19 16:40:35

C#回调

2010-01-20 09:48:44

面向对象

2021-06-07 09:44:10

JavaScript开发代码

2010-03-17 08:49:49

Visual Stud

2009-08-19 17:10:09

C#回调函数

2010-01-20 18:24:51

C++CLI

2023-11-10 16:31:31

2023-10-30 10:29:50

C++最小二乘法

2009-07-31 16:25:29

C#回调函数API应用

2011-06-21 10:17:41

c++内存模型

2020-02-25 16:48:35

AndroidGoogle 移动系统

2010-01-27 16:05:06

C++堆栈

2010-01-21 09:34:57

C++语法

2010-02-03 14:18:44

点赞
收藏

51CTO技术栈公众号