我认为数组是不可复制的

发布于 2025-01-03 04:46:50 字数 1102 浏览 0 评论 0原文

我的印象是数组是不可复制(或可分配)的。

int x[5] = {1,2,3,4,5};
int y[5] = {6,7,8,9,0};

x = y; // Fails to compile

但是,当我将数组放入类中时,复制构造函数和赋值运算符会起作用(我会说如预期的那样,但它不是我所预期的)。

#include <iostream>

struct X
{
    virtual ~X(){} // Just in case it was something to do with POD 
                   // make sure its not a POD
    int x[5];
};

int main()
{
    X   a;

    a.x[0]  = 0;
    a.x[1]  = 1;
    a.x[2]  = 2;
    a.x[3]  = 3;
    a.x[4]  = 4;

    // Make a copy of a and test it
    X   b(a);          
    std::cout << a.x[0] << " : " << b.x[0] << "\n";

    b.x[0]  = 10;
    b.x[1]  = 11;
    b.x[2]  = 12;
    b.x[3]  = 13;
    b.x[4]  = 14;

    // Now that we have modified 'b' make sure it is unique.
    std::cout << a.x[0] << " : " << b.x[0] << "\n";

    // Use assignment and see if it worked.
    b   = a;
    std::cout << a.x[0] << " : " << b.x[0] << "\n";
}

编译并运行

> g++ t.cpp
> ./a.out
0 : 0
0 : 10
0 : 0

这里发生了什么?

I was under the impression that array were non copyable (or assignable).

int x[5] = {1,2,3,4,5};
int y[5] = {6,7,8,9,0};

x = y; // Fails to compile

But when I put an array inside a class the copy constructor and assignment operator work (I would say as expected but its not what I expected).

#include <iostream>

struct X
{
    virtual ~X(){} // Just in case it was something to do with POD 
                   // make sure its not a POD
    int x[5];
};

int main()
{
    X   a;

    a.x[0]  = 0;
    a.x[1]  = 1;
    a.x[2]  = 2;
    a.x[3]  = 3;
    a.x[4]  = 4;

    // Make a copy of a and test it
    X   b(a);          
    std::cout << a.x[0] << " : " << b.x[0] << "\n";

    b.x[0]  = 10;
    b.x[1]  = 11;
    b.x[2]  = 12;
    b.x[3]  = 13;
    b.x[4]  = 14;

    // Now that we have modified 'b' make sure it is unique.
    std::cout << a.x[0] << " : " << b.x[0] << "\n";

    // Use assignment and see if it worked.
    b   = a;
    std::cout << a.x[0] << " : " << b.x[0] << "\n";
}

Compile and Run

> g++ t.cpp
> ./a.out
0 : 0
0 : 10
0 : 0

What is going on here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一桥轻雨一伞开 2025-01-10 04:46:50

默认的复制构造函数和赋值运算符对每个成员单独使用复制构造和赋值。当存在数组时,会对数组的每个元素使用复制构造或赋值(这是非常明确定义的)。

这是第 12.8 节 ([class.copy]) 中的规则:

非联合类X的隐式定义的复制/移动构造函数执行其基类和成员的成员复制/移动。 [ 注意:非静态数据成员的大括号或等于初始化器将被忽略。另请参见 12.6.2 中的示例。 — 尾注] 初始化的顺序与用户定义的构造函数中基类和成员的初始化顺序相同(参见 12.6.2)。令 x 为以下参数之一
构造函数,或者对于移动构造函数,引用参数的 xvalue。每个基本或非静态数据成员都以适合其类型的方式复制/移动:

  • 如果成员是数组,则每个元素都使用x对应的子对象直接初始化;
  • 如果成员 m 具有右值引用类型 T&&,则使用 static_cast(xm) 直接初始化;
  • 否则,基类或成员将直接使用 x 的相应基类或成员进行初始化。


非联合类 X 的隐式定义复制/移动赋值运算符对其子对象执行成员复制/移动赋值。 X 的直接基类首先按照它们在 base-specifier-list 中声明的顺序进行赋值,然后是 X 的直接非静态数据成员>X 按照它们在类定义中声明的顺序进行赋值。令 x 为函数的参数,或者对于移动运算符,为引用该参数的 x 值。每个子对象都以适合其类型的方式分配:

  • 如果子对象是类类型,就好像通过调用operator=,将子对象作为对象表达式,并将x的相应子对象作为单个函数参数(就像通过显式限定;也就是说,忽略任何可能的更多派生类中的虚拟重写函数);
  • 如果子对象是数组,则以适合元素类型的方式分配每个元素
  • 如果子对象是标量类型,则使用内置赋值运算符。

C::C(const C&)C::C(C&) 等之间的签名选择规则还包括引用数组元素类型的语言。

The defaulted copy constructor and assignment operator use copy construction and assignment individually on each member. When there's an array, copy construction or assignment is used on each element of the array (which is quite well-defined).

Here's the rule, from section 12.8 ([class.copy]):

The implicitly-defined copy/move constructor for a non-union class X performs a memberwise copy/move of its bases and members. [ Note: brace-or-equal-initializers of non-static data members are ignored. See also the example in 12.6.2. — end note ] The order of initialization is the same as the order of initialization of bases and members in a user-defined constructor (see 12.6.2). Let x be either the parameter of the
constructor or, for the move constructor, an xvalue referring to the parameter. Each base or non-static data member is copied/moved in the manner appropriate to its type:

  • if the member is an array, each element is direct-initialized with the corresponding subobject of x;
  • if a member m has rvalue reference type T&&, it is direct-initialized with static_cast<T&&>(x.m);
  • otherwise, the base or member is direct-initialized with the corresponding base or member of x.

and

The implicitly-defined copy/move assignment operator for a non-union class X performs memberwise copy/move assignment of its subobjects. The direct base classes of X are assigned first, in the order of their declaration in the base-specifier-list, and then the immediate non-static data members of X are assigned, in the order in which they were declared in the class definition. Let x be either the parameter of the function or, for the move operator, an xvalue referring to the parameter. Each subobject is assigned in the manner appropriate to its type:

  • if the subobject is of class type, as if by a call to operator= with the subobject as the object expression and the corresponding subobject of x as a single function argument (as if by explicit qualification; that is, ignoring any possible virtual overriding functions in more derived classes);
  • if the subobject is an array, each element is assigned, in the manner appropriate to the element type;
  • if the subobject is of scalar type, the built-in assignment operator is used.

The rule for signature selection between C::C(const C&) vs C::C(C&) et al also includes language referring to the array element type.

拥抱没勇气 2025-01-10 04:46:50

数组既不可复制也不可赋值。然而,具有数组成员的结构已经生成了复制构造和复制赋值。这是一个特殊的规则:即它们本身不需要可复制或可分配。

Arrays are neither copyable nor assignable. However, structure with array members have generated copy construction and copy assignment. This is a special rule: i.e. they don't need to be copyable or assignable themselves.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文