C++中object creation(对象创建)与object initialization(对象初始化)的区别
很多C开发者长期混淆对象创建和初始化的概念,二者的核心差异在C11到C++17的prvalue(纯右值)定义迭代中被明确区分,对应关系如下:
1 基础概念定义
- 对象创建:指运行时为对象分配对应大小的内存空间,同时将该内存区域与特定类型绑定的过程,执行完成后一定会产生一个有确定存储地址的实体。
- 对象初始化:指在已经完成创建、绑定了类型的内存空间中写入符合类型要求的初始值的过程,不需要额外分配新的内存,可直接在目标地址上执行。
Richard Smith在相关标准提案中明确提出:值类别体系调整的核心目的就是将prvalue的初始化语义和临时对象创建语义解耦,从标准层面消除无意义的临时对象拷贝/移动开销。
2 C11与C17 prvalue的核心差异
2.1 C++11 prvalue定义
- C++11中prvalue的语义是「立即生成临时对象的表达式」:只要是prvalue,一定会先创建一个临时对象实体,再用这个临时对象拷贝/移动构造目标对象。
- 代码示例:
struct S { S(int) {} S(const S&) = delete; }; S func() { return 1; } // C++11下编译失败:需要可访问的拷贝构造函数完成临时对象到返回值的拷贝 - 对象模型定位:prvalue本身就是一个有确定存储地址的临时对象实体,属于glvalue(泛左值)中的xvalue(到期值)范畴,生命周期默认限定在当前完整表达式作用域内。
2.2 C++17 prvalue定义
- C++17中prvalue的语义被重定义为「初始化器配方」:本身不代表已经创建完成的对象,只是一组用来初始化目标对象的操作序列,只有当场景确实需要对象实体时(比如对prvalue取地址、访问成员、没有绑定到任何目标对象),才会触发临时物化,真正创建临时对象。
- 同样的代码示例在C++17下可以正常编译:
struct S { S(int) {} S(const S&) = delete; }; S func() { return 1; } // C++17下编译通过:prvalue直接在调用方的返回值内存上初始化,没有产生临时对象,不需要拷贝 - 对象模型定位:prvalue本身不属于有存储地址的对象实体,只是不带存储的抽象初始化操作,只有发生临时物化后才会转为有确定存储的xvalue。
3 二者在C++对象模型中的对应定位
- 对象创建对应C++值类别体系中的glvalue(泛左值):所有glvalue(包括lvalue左值、xvalue到期值)都对应已经完成创建、有确定内存地址的对象实体,可以直接取地址、绑定左值引用。
- 对象初始化对应C++值类别体系中的prvalue(纯右值):所有prvalue都只是初始化操作的抽象,没有对应的内存存储,只有当它被用来初始化一个glvalue时,才会将初始化序列作用到glvalue对应的内存上,仅在必要时触发临时物化创建额外的临时对象。
内容的提问来源于stack exchange,提问作者Géry Ogam
相关产品推荐
相关产品推荐

