编译器如何复制数组成员数据?
How does the compiler copy member data that are arrays?
据我所知,无法复制或分配数组,因此:
int a[5] = {1, 2};// 1 2 0 0 0
int b = a;// error
b = a; // error
但是编译器如何通过简单的复制构造函数和复制赋值运算符复制作为 class/struct 类型成员数据的数组?
// trivial struct
struc Arr{
int arr_[7];
};
Arr a = {5, 7, 2, 10, 9, 1, 2};
Arr b = a;// trivial cpy-ctor
a = b; // trivial cpy-assignment operator
- 那么编译器是否会做类似的事情:
this->arr_ = rhs.arr_
?或者它遍历 rhs.arr_
的所有元素并将它们 cpy 分配给它们在 rhs
? 中的对应元素
所有数组和所有对象,都归结为内存中的位和字节。唯一的区别是,具体的,比特和字节,以及它们是如何被解释和使用的
所有位和字节都完全一样。没有特别的,也没有弱势的。
复制这些比特和字节是计算机的工作。编译器只是发出适当的指令,将适当的位和字节从连续内存的一部分复制到连续内存的另一部分。与等效循环非常相似,可以对数组中的每个值进行复制。 C++ 标准不要求编译器以任何特定方式实现它的任何部分。 C++ 标准定义了 effects 和 results (以及语言的每个部分所需的条件)。编译器如何执行此操作完全留给编译器。你不关心它。这是编译器的责任。
C++ 编程语言的规则禁止以这种方式复制单个数组。为什么会这样,那将是一个不同的问题,但就此问题而言,这仅仅是禁止这样做的规则。
但它们确实允许默认构造函数和赋值运算符影响 copy/move 个数组成员。
稍后,您的 C++ 教科书将向您介绍 std::array
模板。您将学习如何像使用数组一样使用它。很难区分它们。它就像一个数组,正确编写的代码将像数组一样使用它。但它不是一个数组。因此,它可以copied/moved完全像你想复制和移动一个等效的数组。
So does the compiler does something like: this->arr_ = rhs.arr_
?
没有。正如你所说,这不会编译。
Or it iterates over all elements of rhs.arr_
and copy-assign them to their coresponding elements in lhs
?
对于复制赋值运算符 - 是。
对于复制构造函数 - 没有。在那里,每个元素都是从另一个数组的相应元素复制构造(未分配)的。像这样:
Arr(const Arr &other) : arr_{other.arr_[0], other.arr_[1], ..., other.arr_[6]} {}
这是手工编写的循环不可能做到的。如果要手动的话,需要手动拼出每个元素。
但是,当然,如果复制构造函数和复制赋值都是微不足道的(意味着它们有效地逐字节复制结构,而不做任何其他事情),它不会复制构造函数复制构造每个元素或复制分配它很重要,因为两者做同样的事情。
请注意,微不足道与编译器生成无关。这个问题让我觉得这里可能有些混乱。
据我所知,无法复制或分配数组,因此:
int a[5] = {1, 2};// 1 2 0 0 0
int b = a;// error
b = a; // error
但是编译器如何通过简单的复制构造函数和复制赋值运算符复制作为 class/struct 类型成员数据的数组?
// trivial struct
struc Arr{
int arr_[7];
};
Arr a = {5, 7, 2, 10, 9, 1, 2};
Arr b = a;// trivial cpy-ctor
a = b; // trivial cpy-assignment operator
- 那么编译器是否会做类似的事情:
this->arr_ = rhs.arr_
?或者它遍历rhs.arr_
的所有元素并将它们 cpy 分配给它们在rhs
? 中的对应元素
所有数组和所有对象,都归结为内存中的位和字节。唯一的区别是,具体的,比特和字节,以及它们是如何被解释和使用的
所有位和字节都完全一样。没有特别的,也没有弱势的。
复制这些比特和字节是计算机的工作。编译器只是发出适当的指令,将适当的位和字节从连续内存的一部分复制到连续内存的另一部分。与等效循环非常相似,可以对数组中的每个值进行复制。 C++ 标准不要求编译器以任何特定方式实现它的任何部分。 C++ 标准定义了 effects 和 results (以及语言的每个部分所需的条件)。编译器如何执行此操作完全留给编译器。你不关心它。这是编译器的责任。
C++ 编程语言的规则禁止以这种方式复制单个数组。为什么会这样,那将是一个不同的问题,但就此问题而言,这仅仅是禁止这样做的规则。
但它们确实允许默认构造函数和赋值运算符影响 copy/move 个数组成员。
稍后,您的 C++ 教科书将向您介绍 std::array
模板。您将学习如何像使用数组一样使用它。很难区分它们。它就像一个数组,正确编写的代码将像数组一样使用它。但它不是一个数组。因此,它可以copied/moved完全像你想复制和移动一个等效的数组。
So does the compiler does something like:
this->arr_ = rhs.arr_
?
没有。正如你所说,这不会编译。
Or it iterates over all elements of
rhs.arr_
and copy-assign them to their coresponding elements inlhs
?
对于复制赋值运算符 - 是。
对于复制构造函数 - 没有。在那里,每个元素都是从另一个数组的相应元素复制构造(未分配)的。像这样:
Arr(const Arr &other) : arr_{other.arr_[0], other.arr_[1], ..., other.arr_[6]} {}
这是手工编写的循环不可能做到的。如果要手动的话,需要手动拼出每个元素。
但是,当然,如果复制构造函数和复制赋值都是微不足道的(意味着它们有效地逐字节复制结构,而不做任何其他事情),它不会复制构造函数复制构造每个元素或复制分配它很重要,因为两者做同样的事情。
请注意,微不足道与编译器生成无关。这个问题让我觉得这里可能有些混乱。