【Boost】boost::shared_from_this值得注意的地方

本文详细解释了在C++中如何正确使用shared_from_this函数,包括其使用的限制条件及应用场景。文章通过对比正确与错误的代码示例,帮助读者理解在哪些情况下可以调用此函数以获取指向自身对象的shared_ptr。

shared_from_this()在一个类中需要传递类对象本身shared_ptr的地方使用shared_from_this函数来获得指向自身的shared_ptr,它是enable_shared_from_this的成员函数,返回shared_ptr。
首先需要注意的是:这个函数仅在shared_ptr的构造函数被调用之后才能使用。原因是enable_shared_from_this::weak_ptr并不在enable_shared_from_this构造函数中设置,而是在shared_ptr的构造函数中设置。
a) 如下代码是错误的:

[cpp] view plaincopyprint?
01.class D:public boost::enable_shared_from_this
02.{
03.public:
04. D()
05. {
06. boost::shared_ptr p=shared_from_this();
07. }
08.};

原因很简单,在D的构造函数中虽然可以保证enable_shared_from_this的构造函数已经被调用,但正如前面所说,weak_ptr还没有设置。
b) 如下代码也是错误的:

[cpp] view plaincopyprint?
01.class D:public boost::enable_shared_from_this
02.{
03.public:
04. void func()
05. {
06. boost::shared_ptr p=shared_from_this();
07. }
08.};
09.void main()
10.{
11. D d;
12. d.func();
13.}

错误原因同上。
c) 如下代码是正确的:

[cpp] view plaincopyprint?
01.void main()
02.{
03. boost::shared_ptr d(new D);
04. d->func();
05.}

这里boost::shared_ptr d(new D)实际上执行了3个动作:
1. 首先调用enable_shared_from_this的构造函数;
2. 其次调用D的构造函数;
3. 最后调用shared_ptr的构造函数。
是第3个动作设置了enable_shared_from_this的weak_ptr,而不是第1个动作。这个地方是很违背c++常理和逻辑的,必须小心。

结论是:不要在构造函数中使用shared_from_this;其次,如果要使用shared_ptr,则应该在所有地方均使用,不能使用D d这种方式,也决不要传递裸指针。

内容概要:本文档介绍了基于3D FDTD(时域有限差分)方法在MATLAB平台上对微带线馈电的矩形天线进行仿真分析的技术方案,重点在于模拟超MATLAB基于3D FDTD的微带线馈矩形天线分析[用于模拟超宽带脉冲通过线馈矩形天线的传播,以计算微带结构的回波损耗参数]宽带脉冲信号通过天线结构的传播过程,并计算微带结构的回波损耗参数(S11),以评估天线的匹配性能和辐射特性。该方法通过建立三维电磁场模型,精确求解麦克斯韦方程组,适用于高频电磁仿真,能够有效分析天线在宽频带内的响应特性。文档还提及该资源属于一个涵盖多个科研方向的综合性MATLAB仿真资源包,涉及通信、信号处理、电力系统、机器学习等多个领域。; 适合人群:具备电磁场与微波技术基础知识,熟悉MATLAB编程及数值仿真的高校研究生、科研人员及通信工程领域技术人员。; 使用场景及目标:① 掌握3D FDTD方法在天线仿真中的具体实现流程;② 分析微带天线的回波损耗特性,优化天线设计参数以提升宽带匹配性能;③ 学习复杂电磁问题的数值建模与仿真技巧,拓展在射频与无线通信领域的研究能力。; 阅读建议:建议读者结合电磁理论基础,仔细理解FDTD算法的离散化过程和边界条件设置,运行并调试提供的MATLAB代码,通过调整天线几何尺寸和材料参数观察回波损耗曲线的变化,从而深入掌握仿真原理与工程应用方法。
<think>我们有一个使用Boost.Asio和Boost.Beast的异步接受操作。具体代码是: acceptor_->async_accept( boost::asio::make_strand(*ioc_), boost::beast::bind_front_handler( &MainSlaveRpcServerImpl::OnAccept, shared_from_this())); 这段代码的作用是异步地接受一个传入的连接。我们逐部分解释: 1. `acceptor_->async_accept`: 这是Boost.Asio中TCP接收器的异步接受操作。它开始一个异步操作来接受一个新的连接。 2. `boost::asio::make_strand(*ioc_)`: 这里创建了一个strand对象。Strand用于确保在同一个strand中分发的多个完成处理程序不会并发执行。这对于避免并发问题(如数据竞争)很有用。`ioc_`是一个指向`io_context`的指针(或可能是`io_context`对象),`*ioc_`获取其引用。`make_strand`从`io_context`创建一个strand。 3. `boost::beast::bind_front_handler`: 这是Boost.Beast提供的一个工具函数,用于将成员函数绑定为异步操作的处理程序。它类似于`std::bind`,但专门设计用于与Boost.Asio和Boost.Beast的完成处理程序一起工作,并且支持处理程序跟踪(handler tracking)。它绑定成员函数的第一个参数(通常是`this`指针)和后续参数(如果有的话)。 4. `&MainSlaveRpcServerImpl::OnAccept`: 这是处理接受连接的回调函数。当有新连接被接受时,这个函数将被调用。它应该是类的成员函数,其签名可能类似于: `void OnAccept(boost::beast::error_code ec, boost::asio::ip::tcp::socket socket);` 5. `shared_from_this()`: 这用于获取当前对象的`std::shared_ptr`。这要求当前对象是由`std::shared_ptr`管理的,并且必须继承自`std::enable_shared_from_this`。使用`shared_from_this`可以确保当处理程序被调用时,对象仍然存在(因为处理程序持有一个`shared_ptr`,从而延长了对象的生命周期)。 注意:使用`shared_from_this()`时,必须确保在调用`shared_from_this()`之前,对象已经被`std::shared_ptr`所管理。否则,会抛出`std::bad_weak_ptr`异常。 因此,这段代码的整体含义是:开始一个异步接受操作,当有新的连接到来时,将其关联到由`ioc_`创建的strand上,然后使用`MainSlaveRpcServerImpl::OnAccept`作为处理程序。同时,通过`shared_from_this()`确保在处理程序被调用时,`MainSlaveRpcServerImpl`对象仍然存在。 现在,我们给出一个完整的示例,展示如何在一个类中实现上述代码: ```cpp #include <boost/asio.hpp> #include <boost/beast.hpp> #include <memory> namespace net = boost::asio; namespace beast = boost::beast; class MainSlaveRpcServerImpl : public std::enable_shared_from_this<MainSlaveRpcServerImpl> { public: MainSlaveRpcServerImpl(net::io_context& ioc) : ioc_(ioc), acceptor_(std::make_shared<net::ip::tcp::acceptor>(ioc, net::ip::tcp::endpoint(net::ip::tcp::v4(), 8080))) { StartAccept(); } void StartAccept() { acceptor_->async_accept( net::make_strand(ioc_), beast::bind_front_handler( &MainSlaveRpcServerImpl::OnAccept, shared_from_this())); } void OnAccept(beast::error_code ec, net::ip::tcp::socket socket) { if (ec) { // 处理错误 return; } // 处理新连接,例如:创建一个会话并开始读取 // ... // 再次开始接受下一个连接 StartAccept(); } private: net::io_context& ioc_; std::shared_ptr<net::ip::tcp::acceptor> acceptor_; }; int main() { net::io_context ioc; auto server = std::make_shared<MainSlaveRpcServerImpl>(ioc); ioc.run(); return 0; } ``` 注意:上面的代码中,`acceptor_`被声明为`std::shared_ptr`,这是因为在多个异步操作中可能需要共享这个接收器。另外,在`OnAccept`中,当处理完一个连接后,再次调用`StartAccept()`以开始接受下一个连接。 但是,请注意,如果`OnAccept`中发生了异常,或者多次调用`StartAccept()`,可能会导致问题。因此,需要确保错误处理得当。 另外,上面代码中,`net::io_context`对象`ioc`在`main`函数中创建,并传递给`MainSlaveRpcServerImpl`的构造函数。然后,我们创建了一个`MainSlaveRpcServerImpl`的共享指针,并运行`io_context`。 现在,根据要求,我们需要在最后提出相关问题: §§相关问题§§: 1. 在Boost.Asio中,strand的作用是什么? 2. 为什么在异步操作中使用`shared_from_this()`? 3. 在`OnAccept`函数中,如果处理新连接时发生异常,会有什么后果?如何避免? 4. 如何修改上述代码以支持SSL连接?</think>### 异步接受连接代码分析 #### 代码解释: ```cpp acceptor_->async_accept( boost::asio::make_strand(*ioc_), // 创建执行strand boost::beast::bind_front_handler( // 绑定处理函数 &MainSlaveRpcServerImpl::OnAccept, shared_from_this())); // 确保对象生命周期 ``` 1. **`async_accept`** - Boost.Asio的异步接受新连接操作 - 当有新连接到达时触发回调 2. **`make_strand(*ioc_)`** - 创建关联到`io_context`的strand对象 - **作用**:确保异步操作的完成处理程序在strand中执行,避免并发访问共享数据时的竞争条件 - 相当于隐式同步机制(无需显式锁) 3. **`bind_front_handler`** - Boost.Beast提供的处理程序绑定工具 - **优势**:自动适配Asio处理程序签名,支持移动语义 - 等价于: ```cpp [self = shared_from_this()](auto&&... args) { self->OnAccept(std::forward<decltype(args)>(args)...); } ``` 4. **`shared_from_this()`** - 关键生命周期管理技术 - **要求**:类必须继承`enable_shared_from_this` - **作用**:让处理程序持有对象的shared_ptr,防止异步操作期间对象被意外销毁 #### 完整实现示例: ```cpp #include <boost/asio.hpp> #include <boost/beast.hpp> #include <memory> namespace net = boost::asio; namespace beast = boost::beast; class MainSlaveRpcServerImpl : public std::enable_shared_from_this<MainSlaveRpcServerImpl> { public: MainSlaveRpcServerImpl(net::io_context& ioc) : ioc_(ioc), acceptor_(ioc, net::ip::tcp::endpoint(net::ip::tcp::v4(), 8080)) { start_accept(); } private: void start_accept() { acceptor_.async_accept( net::make_strand(ioc_), beast::bind_front_handler( &MainSlaveRpcServerImpl::on_accept, shared_from_this())); } void on_accept(beast::error_code ec, net::ip::tcp::socket socket) { if (ec) { // 处理错误: ec.message() return; } // 处理新连接 (启动会话等) // ... // 继续接受下一个连接 start_accept(); } net::io_context& ioc_; net::ip::tcp::acceptor acceptor_; }; // 使用示例 int main() { net::io_context ioc; auto server = std::make_shared<MainSlaveRpcServerImpl>(ioc); ioc.run(); } ``` #### 关键注意事项: 1. **strand的作用** - 当`io_context`在多线程中运行时,strand保证: - 同一strand的处理程序不会并发执行 - 不同strand的处理程序可能并行执行 2. **生命周期管理** - 必须通过`shared_ptr`创建对象: ```cpp auto server = std::make_shared<MainSlaveRpcServerImpl>(ioc); ``` - 构造函数中禁止调用`shared_from_this()`(对象未完全构造) 3. **错误处理** - 必须检查`on_accept`的`error_code`参数 - 典型错误:`operation_aborted`(acceptor关闭时发生)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值