当在参数中构造的对象被析构时

C++: when object constructed in argument is destructed?

本文关键字:对象 析构 参数      更新时间:2023-10-16

当在参数中构造的对象在函数调用之前或之后被析构时?

。下面的代码安全吗?

void f(const char*)
{ ... }
std::string g()
{ ... }
...
f(g().c_str());

它总是对我有效,但我不知道这只是未定义的行为还是它实际上应该工作。

g()是临时的。临时的生命周期延长整个全表达式的整个求值时间(在您的情况下,这将是f(g().c_str())),因此您的使用是安全的,除非f()将指针存储在某处。

§12.2/4在两种上下文中,临时变量在不同于fullexpression结尾的位置被销毁。第一个上下文是当表达式作为定义对象的声明符的初始化项出现时。在这种情况下,保存表达式结果的临时变量应该一直存在,直到对象的初始化完成。[…]

§12.2/5第二个上下文是当引用被绑定到临时对象时。[…]

这两种情况在您的示例中都不适用。

作为表达式求值的一部分构造的临时对象在对包含该表达式的完整表达式求值后被析构,除非它被绑定到一个命名引用。(现行标准草案12.2和1.9为相关章节)。

因此,在您的示例中,用于保存g返回值的临时构造将在f返回后被销毁。

它总是为我工作,但我不知道它只是未定义的行为或者它实际上应该工作。

不,没有未定义行为,因为g()产生的临时对象将在计算完整表达式后被删除,即f()函数的主体。

c++标准n3337 § 12.3/3

当实现引入具有非平凡构造函数(12.1)的类的临时对象时,12.8),它应确保为临时对象调用构造函数。类似地,析构函数应为用非平凡析构函数调用临时函数(12.4)。临时对象作为最后一步被销毁在计算(词法上)包含创建它们的点的完整表达式(1.9)时。这是真的即使该求值以抛出异常结束。析构

的值计算和副作用

c++标准n3337 § 12.3/4

有两种上下文中,临时变量在不同于full-结束的位置被销毁表达式。第一个上下文是调用默认构造函数初始化数组元素的时候。如果构造函数有一个或多个默认参数,销毁在默认值中创建的每个临时参数参数在构造下一个数组元素(如果有)之前进行排序。

c++标准n3337 § 12.3/5

第二个上下文是当引用绑定到临时对象时。(…)