c++ 使用 std::list 隐式复制 *this

标签 c++ list oop reference std

对于一个项目,我有一个对象列表(在我的示例代码中是一个花园)。每个花园都包含一个植物,它具有对其所在花园的引用。这在制作单个花园时非常有效,但是当我创建花园对象的 std::list 时,突然在某处创建了一个拷贝 我不知道,也不知道如何解决它。对象如下:

struct Garden; //Forward declaration
struct Plant {
    Plant(Garden & myGarden) : theGarden(myGarden) { }; //Constructor
    Garden & theGarden; //reference to garden this Plant is in
};
struct Garden {
    Garden(int size) :  thePlant(*this), size(size) { }; //Constructor
    Plant thePlant; //Plant contained in this Garden
    int size;       //Size of this garden
};

到目前为止一切顺利。现在,我可以创建一个独立的花园,或者将一个花园放入列表中。预期的行为是,如果我更改“size”变量,它会在各处发生更改,在 theGarden 中也是如此。但是,在列表中,它仅在“原始”Garden 中发生更改,而不是在引用 theGarden

中发生更改
int main() {
    //Works
    Garden oneGarden(1);
    std::cout << "Expected: 1 1, result: "
            << oneGarden.size << " "
            << oneGarden.thePlant.theGarden.size << std::endl;
    oneGarden.size = 2;
    std::cout << "Expected: 2 2, result: "
            << oneGarden.size << " "
            << oneGarden.thePlant.theGarden.size << std::endl;

    //Does not work!
    std::list<Garden> gardenList;
    gardenList.push_back(Garden(1));
    std::cout << "Expected: 1 1, result: "
            << gardenList.front().size << " "
            << gardenList.front().thePlant.theGarden.size << std::endl;

    gardenList.front().size = 2;
    std::cout << "Expected: 2 2, result: "
                << gardenList.front().size << " "
                << gardenList.front().thePlant.theGarden.size << std::endl;

    return 0;
}

最终输出如下:

Expected: 1 1, result: 1 1
Expected: 2 2, result: 2 2
Expected: 1 1, result: 1 1
Expected: 2 2, result: 2 1

最佳答案

标准容器拥有它们所包含的元素。这意味着插入每个元素时都会对其进行复制。

当您的 Garden被复制时,使用默认的复制构造函数,然后 Plant成员也是默认复制的。然而,这意味着新的Plant包含对 Garden 的引用.

在这种情况下,旧的 Garden是临时的gardenList.push_back(Garden(1))所以它不仅不正确Garden ,但它是 Garden那甚至不再存在了。简而言之,您正在通过悬空引用(具有未定义的行为)读取大小,并[un?]幸运地看到其背后的旧值。

您应该为 Garden 编写一个复制构造函数复制其 Plant在各个方面除了新的Plant应该引用新的 Garden ,而不是仅仅复制旧的引用。

使用新的 C++11 功能实际上可以避免该拷贝以及由此产生的整个问题:

gardenList.emplace_back(1);

现在,the Garden in the list is created in-place ,并且不会执行任何复制。

但是,您仍然应该使用 Garden 修复底层设计问题。 ,即使您以这种方式解决问题。

关于c++ 使用 std::list 隐式复制 *this,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24307077/

相关文章:

python - Python 中的相同对象问题

c++ - 类包含其他类问题的字段

c++ - 替代函数语法差异

c++ - C++ 中的精度

r - 将具有不同向量长度的列表转换为 R 中的数据帧

java - 根据每个对象内的 List<String> 过滤 List<Object>

Python:一种从 Python 字典中删除空列表的优雅方法

ios - 具有适应不同屏幕分辨率的 View 的 MVC 模式

c++ - RealSense OpenCV 深度图像太暗

c++ - 英特尔 C++ 编译器了解执行了哪些优化