“调用销毁者置于末尾”原则
核心思想:
 在一个对象的方法中,如果需要调用一个可能导致该对象自身被销毁的回调或函数,那么这个调用必须是该方法中的最后一个操作。之后不应再有任何访问对象成员(this 指针)的代码。
问题场景:
 在事件驱动和异步编程中,一个对象(如 TcpConnection)的方法(如 handleClose)经常需要调用一个由其所有者(如 TcpServer)设置的回调(如 closeCallback_)。这个回调的职责通常是释放对该对象的最后一个 shared_ptr,从而触发对象的析构。
把它想象成一个特工执行任务的场景:
- 对象:特工。
- 方法 handleClose():特工执行的“终极任务”。
- 回调 closeCallback_:任务中的一个步骤是“按下自毁按钮”。
- 原则:“按下自毁按钮”必须是特工在任务清单上的最后一项。如果他按下按钮后还想去喝杯咖啡(执行后续代码),那么他就会和基地一起被炸飞。
危险的写法:
void MyObject::doSomethingAndDie() {// ...potentiallySuicidalCallback_(); // 这个回调可能会 delete this;// 危险!如果对象已被销毁,这里的代码会访问无效内存。this->member_ = 10; LOG_INFO << "Task finished.";
}void MyObject::doSomethingAndDie() {// ...// 为了确保在函数内部 this 有效,可以先创建一个临时的 shared_ptrstd::shared_ptr<MyObject> guardThis = shared_from_this(); // 执行所有其他操作...// 将可能导致自毁的调用放在绝对的最后。potentiallySuicidalCallback_(guardThis);
}