8.7.3 The return statement
返回语句中的表达式或花括号初始化列表(expr-or-braced-init-list)称为它的操作数。
- 不带操作数的返回语句只能用于①返回类型为cv void的函数、②构造函数、③析构函数中。
- 操作数类型为void的返回语句只能用于返回类型为cv void的函数中。
- 带有任何其他类型操作数的返回语句只能用于返回类型非cv void的函数中;
- 返回语句通过从操作数拷贝初始化,来初始化当前(显式或隐式的)函数调用的返回对象(可能是泛左值或纯右值)。
【注释:如果操作数不是纯右值,或者其类型与函数的返回类型不同,则返回语句可能会调用构造函数来执行操作数的复制或移动(以构造要返回的对象)。如果返回的是具有自动存储周期的变量,则与返回语句关联的拷贝操作可以被省略或转换为移动操作([class.copy.elision])。 ——注释结束】
【示例:
1 | std::pair<std::string,int> f(const char* p, int x) |
——示例结束】
返回对象的析构函数被潜在调用(potentially invoked)([class.dtor],[except.ctor])
【示例:
1 | class A |
——示例结束】
对于构造函数、析构函数或返回类型为cv void的非协程函数(这些函数(可以)没有显式返回语句),执行到函数末尾(Flowing off the end)等价于一个没有操作数的返回语句。除此之外,如果控制流流出除main函数或协程([dcl.fct.def.coroutine])以外的其它函数(即缺少返回语句),将导致未定义行为。
Paw5zx个人理解:点击查看更多
返回语句通过从操作数拷贝初始化,来初始化当前(显式或隐式的)函数调用的返回对象(可能是泛左值或纯右值)。
这里描述的是RVO(返回对象是纯右值)和NRVO(返回对象是泛左值)机制
1 | struct T |
对于RVO,C++17已经强制要求,直接在返回对象上构造
如果操作数不是纯右值,或者其类型与函数的返回类型不同,则返回语句可能会调用构造函数来执行操作数的复制或移动(以构造要返回的对象)。如果返回的是具有自动存储周期的变量,则与返回语句关联的拷贝操作可以被省略或转换为移动操作。
1 |
|
不考虑NRVO,在make_nrvo中,需要用local初始化返回对象,调用了移动构造函数。NRVO开启后会优化这一步。
函数调用结果的拷贝初始化,先序于由返回语句操作数所确立的完整表达式([intro.execution])末尾的临时对象的析构。而后者又先序于包含该返回语句的块内的局部变量([stmt.jump])的析构。
Paw5zx个人理解:点击查看更多
不用上述示例因为local是一个id-expression而不是full-expression