当返回一个用带括号的init列表初始化的对象时,我保证有一对构造函数和析构函数调用吗?
Am I guaranteed a single pair of constructor and destructor calls when returning an object initialized with braced init list?
以以下类为例
#include <iostream>
using namespace std;
class A{
private:
int a_;
int b_;
A(const A&) = delete;
A& operator=(const A&) = delete;
A(A&&) = delete;
A& operator=(A&&) = delete;
public:
A(int a, int b) : a_{a}, b_{b}{cout<<"constructedn";}
void ephemeral() const{cout<<"operationn";}
~A(){cout<<"destructedn";}
};
A make_A(int a, int b){
return {a, b};
}
int main(){
make_A(1, 2).ephemeral();
return 0;
}
给出了预期的结果。
构造对象,执行操作,然后对其进行析构。然而,我担心这是否得到保证。我主要担心的是,由于标准给予编译器的自由,我是否会看到任何我没有意识到的影响。
我不认为copy-省略是这里的一个因素,因为所有的move和copy构造函数都被声明为已删除,所以它们怎么可能被调用呢?
唯一被调用的构造函数是接受两个整数的构造函数。我能确定这将在编译器、平台和优化级别上保持一致吗?我怀疑答案是肯定的,但可能有微妙之处。
return {a,b};
时直接构造返回值
没有创建临时的、逻辑的或其他的。没有遗漏。
该返回值在main
的返回上下文中可用。你可以称之为.ephemeral()
操作。在完整表达式的末尾,它将超出作用域,除非您将其"存储"在A const&
(引用生命周期扩展启动)或A&&
(同上)或auto const&
或auto&&
变量中,如下所示:
auto&& a = make_A(1, 2);
a.ephemeral();
在上面的例子中,没有复制发生。
这些操作都不会导致不符合标准的副本。
你是正确的,在某些情况下,复制结构可以被省略掉。省略是指两个对象的标识和生存期合并。所以如果make_A
read:
A make_A(int a, int b){
A r{a,b};
return r;
}
r
可以在返回值中省略。然而,在这里,编译器会要求定义A(A const&)
或A(A&&)
,因此它不会与A
一起编译。在实践中,一旦检查了它们的定义,它就不会调用它们,因为make_A
中的r
将被省略为与make_A
的返回值相同的对象。
相似的,
A a = make_A(1,2);
省略make_A
返回的临时变量,使其与命名变量a
相同。省略是暂时的,因此也可以在 make_A
中同时省略变量。在本例中,还需要存在A(A&&)
或A(A const&)
。
通过删除move/copy函数,它们不能被调用,因此对象不能被复制。每个构造函数只能调用一个析构函数(除非手动构造或析构)。
如果代码试图调用它们,它将在编译时生成一个错误。
在c++ 17中,你甚至可以使用return A(a,b);
和类似的保证。
你也可以A a = make_A(1,2);
和类似的保证发生。
这被描述为"保证省略",而是将一些操作转换为"如何构造某些东西的描述"。
所以在某些情况下,你可以在c++ 03或c++ 11或c++ 14中做需要移动或复制因子的事情,但在c++ 17中现在可以做类似于"省略"的事情,不再需要移动或复制因子
- 构造函数正在调用一个使用当前类类型的函数
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- 在模板化类的构造函数中调用构造函数
- 为什么从另一个构造函数内部调用C++构造函数不修改类变量?
- 在成员构造函数之后调用基类构造函数
- 为什么在传递给函数而不是构造函数时调用析构函数?
- 我不知道为什么复制构造函数的调用在 c++ 中不稳定
- 如何构造一个类型特征,可以判断一个类型的私有方法是否可以在另一个类型的构造函数中调用?
- 如何执行参数化构造函数的调用?
- 为什么转换运算符调用复制构造函数两次,而等效函数只调用它一次
- C++构造函数和调用函数
- std::vector 范围构造函数可以调用显式转换吗?
- C++:如何在对象构造过程中调用初始值设定项列表之外的成员构造函数
- 函数中调用的构造函数的顺序
- 从类似构造函数的调用返回模板化智能指针
- 使用范围解析运算符时,在构造函数中调用虚拟方法是否安全?
- 构造函数中调用没有匹配函数 - C++ 11
- GCC __attribute__((constructor)) 在对象构造函数之前调用
- 重载运算符 new(),为什么构造函数被调用两次?