大宝剑*_*大宝剑 8 c++ assignment-operator
比如,它让我困惑:
struct A {
// some fileds...
char buf[SIZE];
};
A a;
a = a;
Run Code Online (Sandbox Code Playgroud)
通过A的字段buf
,看起来默认的赋值操作可能会调用类似于memcpy
将对象X分配给Y的东西,所以如果将对象分配给自身并且没有定义明确的赋值操作,a = a;
如上所述.
memcpy手册页:
DESCRIPTION
The memcpy() function copies n bytes from memory area src to memory area dest. The memory areas must not overlap. Use memmove(3) if the memory areas do overlap.
Run Code Online (Sandbox Code Playgroud)
如果使用memcpy
,可能会发生一些未定义的行为.
那么,C++对象中的默认赋值操作行为是什么?
R. *_*des 12
赋值运算符不是根据memcpy
(§12.8/ 28)定义的.
非联合类X的隐式定义的复制/移动赋值运算符执行其子对象的成员复制/移动分配.首先按照它们在base-specifier-list中的声明顺序分配X的直接基类,然后按照它们在类定义中声明的顺序分配X的直接非静态数据成员. .设x是函数的参数,或者对于move运算符,是指参数的xvalue.每个子对象都以适合其类型的方式分配:
[...]
- 如果子对象是一个数组,则以适合于元素类型的方式分配每个元素;
[...]
如您所见,每个char
元素都将单独分配.这总是安全的.
但是,在as-if规则下,编译器可以用a替换它,memmove
因为它具有相同的char
数组行为.它也可以用memcpy
if 替换它,如果它可以保证memcpy
会导致这种相同的行为,即使理论上这样的事情是未定义的.编译器可以依赖于理论上未定义的行为; 存在未定义行为的原因之一是编译器可以将其定义为更适合其操作的任何内容.
实际上,在这种情况下,编译器可以进一步采用as-if规则,而根本不对数组执行任何操作,因为这也会导致相同的行为.