【问题标题】:Copy an object and make both share a member variable (C++)复制一个对象并使两者共享一个成员变量(C++)
【发布时间】:2018-11-27 18:14:24
【问题描述】:

我一直在思考和搜索这个问题,但我无法解决这个问题。 我想要一个对象,当复制到另一个对象时,两个对象共享某些成员变量。所以,当我改变object1的成员变量的值时,它也改变了object2中的变量。示例:

class ABC {
public:
    int a = 5;
    //...
}

int main() {
    ABC object1;

    ABC object2 = object1;

    object2.a = 7;      // now, object1.a is equal to 7
    object1.a = 10;     // now, object2.a is equal to 10
}

我知道复制构造函数,但我不确定它是否适用于这里或有 更好的方法。我一直在考虑使用指针或引用,但无法成功。 请注意,我不希望所有对象共享同一个变量。

【问题讨论】:

  • 如果您希望此类的所有对象共享同一个变量,您可以将其设为静态。如果您只希望这两个共享一个变量并且该连接使用复制构造函数或赋值运算符进行通信,则可以使用共享指针变量。
  • 在 C++ 中,在多个实例之间共享对数据的引用会破坏复制语义(如果您使用复制构造函数来共享该数据)。也就是说,当您复制某些内容时,它们应该完全不相交,以便更改一个副本不会影响另一个副本。这很重要,因为编译器理解复制语义并在优化代码时使用它。有关这方面的更多信息,您可能想查看一些 Sean Parent 在 YouTube 上的演讲。
  • 话虽如此,你可以考虑一个工厂函数,比如unique_ptr<ABC> createShallowCopy(const ABC& itemToCopy),这样读者就知道这不是一个正确的副本,编译器不会把这个函数当作复制构造函数。
  • @TimJohns 这是错误的。在不同对象之间共享公共引用绝不会“破坏复制语义”,也不会妨碍编译器优化。例如,如果我想在类似对象之间共享一个相同的 const large_data_structure&,这会更快,以避免不必要地复制所述对象。
  • That is, when you copy something, they should be completely disjoint so that changing one copy does not affect the other. 通常这是一个很好的做法,但是有足够多的情况可以接受,甚至更好。 This is important because the compiler understands copy semantics and uses that when optimizing your code. 从技术上讲这是正确的,但最终会产生误导;共享数据(使用引用或指针)不会降低编译器优化代码的能力。

标签: c++ class copy-constructor member-variables


【解决方案1】:

你需要的是一个指针。指针指向对象,然后所有复制第一个对象的对象只需复制指针,以便它们都指向同一事物。为了让生活更轻松,我们可以使用std::shared_ptr 为我们管理分配和释放。比如:

#include <memory>

class Foo
{
private:
    std::shared_ptr<int> bar;
public:
    Foo() : bar(std::make_shared<int>()) {}
    int& getBar() { return *bar; }
};

int main()
{
    Foo a;
    a.getBar() = 7;
    Foo b = a;
    b.getBar() = 10;
    // now getBar returns 10 for both a and b
    Foo c;
    // a and b are both 10 and c is 0 since it wasn't a copy and is it's own instance
    b = c;
    // now b and c are both 0 and a is still 10
}

【讨论】:

  • 谢谢,这正是我所需要的。现在我知道去哪里找了。效果很好。
  • 请记住,这里的默认赋值运算符将导致目标开始共享源的 bar 并忘记它的旧共享对象(而不是复制值);如果这不是您想要的行为,您将需要编写一个赋值运算符
猜你喜欢
  • 2019-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
相关资源
最近更新 更多