更新时间:2022-05-27 04:57:42
成员上的const
限定符使编译器假定-在初始化对象之后-不得以任何方式更改这些成员,并且可以相应地优化代码(例如,参见@Ajay Brahmakshatriya评论).
The const
-qualifiers on members let the compiler assume that - after an object has been initialized - these members must not be altered through any way, and it may optimise code accordingly (cf, for example, @Ajay Brahmakshatriya comment).
因此,必须将 initialization 阶段与随后应用 assignments 的各个阶段区分开,例如,从何时开始,编译器可能会假定对象已初始化并具有一种有效的类型.
So it is essential to distinguish the initialization phase from the subsequent phases where assignments would apply, i.e. from when on may a compiler assume that an object got initialized and has an effective type to rely on.
我认为您的示例与您引用的已接受答案之间存在主要区别.在此 SO答案中,具有常量限定成员类型的目标聚合对象是通过malloc
创建的:
I think there is a main difference between your example and that in the accepted answer you cited. In this SO answer, the target aggregate object with const-qualified member types is created through malloc
:
ImmutablePoint init = { .x = x, .y = y };
ImmutablePoint *p = malloc(sizeof *p);
memcpy(p, &init, sizeof *p);
根据有关如何访问对象的存储值的规则(请参见在线c标准草稿),则p
目标对象将在执行memcpy
的过程中首次获得其有效类型;那么有效类型就是源对象init
的类型,并且获得malloced
的对象上的第一个memcpy
可以看作是初始化.但是,之后修改目标对象的const成员将是UB(我认为即使第二个memcpy
也会是UB,但这可能是基于意见的).
According to the rules on how a stored value of an object may be accessed (cf. this part of an online c standard draft), the p
-target object will get its effective type the first time in the course of performing memcpy
; the effective type is then that of the source object init
, and the first memcpy
on an object that got malloced
can be seen as an initialization. Modifying the target object's const members afterwards, however, would be UB then (I think that even a second memcpy
would be UB, but that's probably opinion based).
6.5表达式
87)分配的对象没有声明的类型.
但是,在您的示例中,目标对象dst
通过其定义struct vector dst;
已经具有声明的类型.因此,dst
成员上的const限定符在应用memcpy
之前就已经存在,并且必须将其视为分配而不是初始化.
In your example, however, the target object dst
already has a declared type through it's definition struct vector dst;
. Hence, the const-qualifiers on dst
's members are already in place before the memcpy
is applied, and it has to be seen as an assignment rather than an initialization.
因此,在这种情况下,我将投票给UB.
So I'd vote for UB in this case.