复制带有指向另一个对象的引用或指针的对象 [duplicate]

Copying an object with a reference or pointer to another object [duplicate]

提问人:torres 提问时间:9/28/2023 最后编辑:torres 更新时间:9/28/2023 访问量:45

问:

我正在设计一个游戏,我需要复制某些组件。

这是我需要的:

class Common { };

class Component
{
private:

    Common &_commRef;

public:
    
    Component(Common &commRef) :_commRef{ commRef }{}
};

int main()
{
    Common common;
    Component componentA(common);
    Component componentB(common);
    Component compCopy(common);
    
    compCopy = componentA; //can't do this
    
    return 0;
}

但是,由于引用无法重新插入,因此我无法复制到 。这个问题在这里被问到:复制一个带有引用类型的成员变量的 C++ 类,但我的问题是关于答案本身。componentAcompCopy

因此,可能的解决方案是:

将原始指针传递给 Component 的构造函数,而不是引用

class Common { };

class Component
{
private:

    Common *_commPtr;

public:
    
    Component(Common *commPtr) :_commPtr{ commPtr }{}
};

int main()
{
    Common common;
    Component componentA(&common);
    Component componentB(&common);
    Component compCopy(&common);
    
    compCopy = componentA; 
    
    return 0;
}

我不确定这是否是个好主意,因为班级现在可以做一些奇怪的事情,比如打电话。ComponentdeletecommPtr

传递智能指针

class Common { };

class Component
{
private:

    std::shared_ptr<Common> _commPtr;

public:
    
    Component(std::shared_ptr<Common> commPtr) :_commPtr{ commPtr }{}
};

int main()
{
    std::shared_ptr<Common> commPtr = std::make_shared<Common>();
    Component componentA(commPtr);
    Component componentB(commPtr);
    Component compCopy(commPtr);

    compCopy = componentA; 
    
    return 0;
}

使用这种方法,我们在第一种方法中没有问题,但我不必要地在堆上创建一个对象,而不是第一种方法在堆栈上创建它。我的理解是使用堆栈,除非我们正在创建大型对象(创建对象经常被误用/过度使用?Commonnew

使用参考包装器(如链接的答案中所示):

class Common { };

class Component
{
private:

    std::reference_wrapper<Common> _commRef;

public:
    
    Component(Common &commRef):_commRef{commRef}
    {}
};

int main()
{
    
    Common common;
    Component componentA(common);
    Component componentB(common);
    Component compCopy(common);

    compCopy = componentA; 
    
    return 0;
}

我应该更喜欢哪一个?或者,有没有其他方法?

使用引用包装器看起来最干净。它有缺点吗?

C++ 参考 智能指针

评论

1赞 Osyotr 9/28/2023
我会说 (1) + 复制/移动构造函数,因为有一个最小惊喜的原则。您无法复制引用,因此任何模拟引用的尝试都是模棱两可的。
0赞 torres 9/28/2023
@Osyotr 是的,我同意。但是,在某些情况下,我认为我需要副本(我在这里可能是错的)例如,在运行测试/模拟时(组件在棋盘游戏中重复游戏板),我必须测试移动,然后重置板。我可以创建一个重置方法而不是复制,但我正在寻找一种快速肮脏的方法:)
1赞 Remy Lebeau 9/28/2023
@torres,我会说坚持下去,这样它就可以处理常见情况,同时仍然能够根据需要引用新副本。shared_ptr
0赞 torres 9/28/2023
@RemyLebeau好吧,这是有道理的,而且我相信,它将具有最可预测的行为。谢谢!
1赞 Sam Varshavchik 9/28/2023
"...因为类 Component 现在可以做一些奇怪的事情,比如在 commPtr 上调用 delete”。您可能会惊讶地发现,这也可以通过引用来完成:获取引用对象的地址并调用它。它是深邃的、黑暗的、秘密的,只有少数留着胡子的 C++ 大师才知道:引用实际上是一个指针,唯一的区别是每次使用时都会自动与引用变量一起使用。Abracadabra:指针现在是一个参考。不能重新拔插引用的事实完全是因为这个原因。delete*

答: 暂无答案