如何正确存储并使用shared_ptr地址以修改外部智能指针对象?
我尝试传递一个可能为空的shared_ptr<MyObject>对象,期望在Command类中操作或创建CommandManager中的globalObj,但当前代码虽传递了地址,修改却无法同步到CommandManager中。以下是我的代码:
#include <iostream> #include <memory> struct MyObject { int i = 0; MyObject(const int i_) : i(i_) {} }; struct Command { std::shared_ptr<MyObject> cmdObj; Command(std::shared_ptr<MyObject>& obj) : cmdObj(obj) { std::cout << "Store and use this address: " << &obj << std::endl; // [1] } void execute() { if (cmdObj == nullptr) { cmdObj = std::make_shared<MyObject>(42); } else { cmdObj->i = 7; } } }; struct CommandManager { std::shared_ptr<MyObject> globalObj; // [1] CommandManager() { globalObj = nullptr; } void runCommand() { Command cmd(globalObj); cmd.execute(); } }; int main() { CommandManager cm; std::cout << "cm.globalObj address: " << &cm.globalObj << std::endl; // [1] cm.runCommand(); if (cm.globalObj == nullptr) { std::cout << "globalObj is null" << std::endl; } else { std::cout << "globalObj is " << cm.globalObj->i << std::endl; } }
解决方案
问题核心:当前Command里的cmdObj是shared_ptr的独立副本,修改这个副本只会改变自身指向,不会影响原globalObj。要实现同步修改,必须直接操作原shared_ptr对象本身,而非它的副本。
方法1:使用shared_ptr的引用(推荐)
将Command中的cmdObj改为引用类型,这样所有操作都会直接作用于原globalObj:
#include <iostream> #include <memory> struct MyObject { int i = 0; MyObject(const int i_) : i(i_) {} }; struct Command { // 修改为引用类型 std::shared_ptr<MyObject>& cmdObj; // 构造函数初始化引用 Command(std::shared_ptr<MyObject>& obj) : cmdObj(obj) { std::cout << "Store and use this address: " << &obj << std::endl; } void execute() { if (cmdObj == nullptr) { // 直接修改原shared_ptr的指向 cmdObj = std::make_shared<MyObject>(42); } else { cmdObj->i = 7; } } }; struct CommandManager { std::shared_ptr<MyObject> globalObj; CommandManager() { globalObj = nullptr; } void runCommand() { Command cmd(globalObj); cmd.execute(); } }; int main() { CommandManager cm; std::cout << "cm.globalObj address: " << &cm.globalObj << std::endl; cm.runCommand(); if (cm.globalObj == nullptr) { std::cout << "globalObj is null" << std::endl; } else { std::cout << "globalObj is " << cm.globalObj->i << std::endl; } }
方法2:使用shared_ptr的指针
如果Command需要长期持有对象(引用可能存在生命周期失效风险),可以存储指向shared_ptr的指针:
#include <iostream> #include <memory> struct MyObject { int i = 0; MyObject(const int i_) : i(i_) {} }; struct Command { // 修改为指针类型 std::shared_ptr<MyObject>* cmdObj; Command(std::shared_ptr<MyObject>& obj) : cmdObj(&obj) { std::cout << "Store and use this address: " << &obj << std::endl; } void execute() { if (*cmdObj == nullptr) { // 通过指针修改原shared_ptr的指向 *cmdObj = std::make_shared<MyObject>(42); } else { (*cmdObj)->i = 7; } } }; struct CommandManager { std::shared_ptr<MyObject> globalObj; CommandManager() { globalObj = nullptr; } void runCommand() { Command cmd(globalObj); cmd.execute(); } }; int main() { CommandManager cm; std::cout << "cm.globalObj address: " << &cm.globalObj << std::endl; cm.runCommand(); if (cm.globalObj == nullptr) { std::cout << "globalObj is null" << std::endl; } else { std::cout << "globalObj is " << cm.globalObj->i << std::endl; } }
两种方法运行后都会输出globalObj is 42,说明修改已同步到CommandManager的globalObj中。
内容的提问来源于stack exchange,提问作者Markstar
相关产品推荐
相关产品推荐

