34

这是我想了很久的事情。举个例子:

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_copymemcpy或或memmove或什么?

4

2 回答 2

46

这就是标准在 12.8(复制类对象)中所说的。复制构造:

每个子对象都以适合其类型的方式复制:

  • 如果子对象是类类型,则使用该类的复制构造函数;
  • 如果子对象是一个数组,则以适合元素类型的方式复制每个元素;
  • 如果子对象是标量类型,则使用内置赋值运算符。

复制作业:

每个子对象都以适合其类型的方式分配:

  • 如果子对象是类类型,则使用该类的复制赋值运算符(好像通过显式限定;也就是说,忽略更多派生类中任何可能的虚拟覆盖函数);
  • 如果子对象是数组,则以适合元素类型的方式分配每个元素;
  • 如果子对象是标量类型,则使用内置赋值运算符。
于 2010-11-12T11:54:25.547 回答
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
  • 从结果的第一行,我们可以看到至少复制了一些东西(它要么是数组中的元素,要么是复制了数组指针)。
  • 从接下来的两行中,我们可以看到更改复制分配对象和复制构造对象的数组并没有改变原始数组。因此我们得出结论,复制的是元素而不是数组指针。

希望这个例子很清楚。

于 2018-11-15T00:47:05.730 回答