C++数组成员在复制控制函数中如何处理?

35

这是我长期以来一直想知道的问题。看下面的例子:

struct matrix
{
    float data[16];
};

我知道在这个特定的例子中默认构造函数和析构函数的作用(什么也不做),但是复制构造函数和赋值运算符又是怎样的呢?

struct matrix
{
    float data[16];

    // automatically generated copy constructor
    matrix(const matrix& that) : // What happens here?
    {
        // (or here?)
    }

    // automatically generated copy assignment operator
    matrix& operator=(const matrix& that)
    {
        // What happens here?

        return *this;
    }
};

这是否涉及std::copystd::uninitialized_copymemcpymemmove等内容?

2个回答

48
这是标准中12.8(复制类对象)的规定。复制构造函数:
每个子对象按其类型适当的方式进行复制:
- 如果子对象是类类型,则使用该类的复制构造函数; - 如果子对象是数组,则按照元素类型适当的方式复制每个元素; - 如果子对象是标量类型,则使用内置赋值运算符。
复制赋值运算符:
每个子对象按其类型适当的方式进行分配:
- 如果子对象是类类型,则使用该类的复制赋值运算符进行分配(就像通过显式限定一样;也就是说,忽略任何可能在更派生类中重写的虚拟覆盖函数); - 如果子对象是数组,则按照元素类型适当的方式对每个元素进行分配; - 如果子对象是标量类型,则使用内置赋值运算符。

1

两者都复制数组中的元素(而不是什么也不做或者只复制指针)。

struct X
{
    char data_[100];
};


int main () 
{
    X orig, copy_assign;
    orig.data_[10] = 'a';
    copy_assign = orig;
    X copy_constructor(orig);
    printf("orginal10:%c, copy_assign10:%c, copy_constructor10:%c\n",orig.data_[10],copy_assign.data_[10],copy_constructor.data_[10]);
    copy_assign.data_[10] = 'b';
    printf("original10:%c, copy_assign10:%c, copy_constructor10:%c\n",orig.data_[10],copy_assign.data_[10],copy_constructor.data_[10]);
    copy_constructor.data_[10] = 'c';
    printf("original10:%c, copy_assign10:%c, copy_constructor10:%c\n",orig.data_[10],copy_assign.data_[10],copy_constructor.data_[10]);
    return 0;
}

运行结果:

orginal10:a, copy_assign10:a, copy_constructor10:a
original10:a, copy_assign10:b, copy_constructor10:a
original10:a, copy_assign10:b, copy_constructor10:c
  • 从结果的第一行可以看出,至少复制了某些内容(可能是数组中的元素,也可能是数组指针被复制)。
  • 从接下来的两行中,我们可以看到更改复制分配对象和复制构造对象的数组并没有改变原始数组。因此我们得出结论,元素被复制而不是数组指针。

希望这个例子很清楚。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接