如何根据参考修饰符进行深层或浅层复制?

时间:2020-04-22 01:55:11

标签: c++ c++17

比方说,我有A类,带有内部指针。我声明变量:

A a;

A b;

A&c;

我希望“ a = b”(或“ b = a”)进行深度复制,但我希望“ c = a”(或“ c = b”)充当参考并反映变化将来做成a或b。

我本以为c的浅表复制/引用行为是自动的,但是我认为我的赋值运算符可能过载得很差,因为当我说“ c = a”时它仍然被调用,并且仍然进行深表复制。 / p>

现有的赋值运算符签名为:A&运算符=(const A&a);

我如何具有重载的赋值运算符以进行深度复制,但如何保持类似引用的引用行为?

3 个答案:

答案 0 :(得分:3)

这不是引用在c ++中的工作方式。引用仅在声明时绑定到另一个变量。实际上,这段代码

A& c;

甚至不会编译。您必须将其绑定到其他变量,例如:

A& c = a;  // does not call operator= (no deep copy)

但是,在这之后,如果您执行c,则分配给c = b;会调用副本分配运算符,这会进行深度复制。请注意,由于c已绑定到a,所以这与将b分配给a相同。

答案 1 :(得分:3)

C ++希望引用的行为就像引用所绑定的对象的另一个名称一样。它明确地不希望用户能够重新绑定引用,以使绑定的引用引用另一个对象。

这样,如果a是对c的引用,那么a的每次使用都将与您使用std::reference_wrapper时的行为完全相同(有一些小例外,没有其中适用于您的使用)。您不能“保持类似参考的行为;”这根本不是语言功能的目的。

您想要的是一个指针(或c = &a,但是指针通常是您想要的)。这样,您可以区分重新绑定操作(*c = a)和值分配操作({{1}})。

答案 2 :(得分:1)

A&c;

这不是我们在C ++中定义reference变量的方式。参考应该是 在定义时绑定到对象。创建之后,便无法将它们更改为指向其他内容。

正确的方法:

A&c = a;

对于以上几点,没有调用构造函数。只是c被用作对象a的别名。但是,如果您执行c = b,则将调用对象copy assignmenta的{​​{1}},如下所示。

我本以为c的浅表复制/引用行为是自动的,但是我认为我的赋值运算符可能过载得很差,因为当我说“ c = a”时它仍然被调用,并且仍然进行深表复制。 / p>

b调用对象c = aa的副本构造函数。 C ++中的Pointer对您来说是更好的选择。可以更改它们以指向任何对象。请参见下面的示例,了解我在b函数中的指针的示例,并且它执行main复制(请参见未调用任何构造函数或赋值运算符)。

显示哪个对象被调用的示例:

shallow

输出:

#include <iostream>

class A {

public:
    A(void)
    {
        std::cout << "__CONSTRUCTOR__" << std::endl;
        std::cout << this << std::endl;
    }
    A(const A& )
    {
        std::cout << "__COPY_CONSTRUCTOR__" << std::endl;
        std::cout << this << std::endl;
    }
    const A& operator=(const A& other)
    {
        std::cout << "__COPY_ASSIGNMENT__" << std::endl;
        std::cout << this << " and " << &other <<  std::endl;
        return *this;
    }
    ~A(void)
    {
        std::cout << "__DESTRUCTOR__" << std::endl;
        std::cout << this << std::endl;
    }
};


int main(void)
{
    std::cout << "Example with reference" << std::endl;
    std::cout << "------------ CREATING A ------------" << std::endl;
    A a;
    std::cout << "------------ CREATING B ------------" << std::endl;
    A b;
    std::cout << "------------ CREATING C ------------" << std::endl;
    A& c = b;
    std::cout << "-------------- C = A ---------------" << std::endl;
    c = a;


    std::cout << std::endl;
    std::cout << std::endl;

    std::cout << "Example with pointers" << std::endl;
    std::cout << "------------ CREATING D ------------" << std::endl;
    A *d;
    std::cout << "-------------- D = &A --------------" << std::endl;
    d = &a;
    std::cout << "-------------- D = &B --------------" << std::endl;
    d = &b;

    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << "Leaving the program" << std::endl;
}
相关问题