当参数构造的对象被破坏时,在函数调用之后?
E.g。以下代码是否安全?
void f(const char*)
{ ... }
std::string g()
{ ... }
...
f(g().c_str());
它总是对我有用,但我不知道它只是未定义的行为,或者它实际上应该有效。
答案 0 :(得分:2)
它总是对我有用,但我不知道它只是未定义的行为 或者它实际上应该工作。
不,没有未定义的行为,因为在评估完整表达式(即f()函数的主体)之后,将删除g()生成的临时对象。
C ++标准版n3337 § 12.3 / 3
当一个实现引入一个具有非平凡构造函数的类的临时对象时(12.1, 12.8),它应确保为临时对象调用构造函数。同样,析构函数应该是 用非平凡的析构函数(12.4)调用临时函数。临时对象作为最后一步被销毁 在评估全表达式(1.9)时(词法上)包含创建它们的点。这是真的 即使该评估以抛出异常结束。破坏的价值计算和副作用
C ++标准版n3337 § 12.3 / 4
有两种情况下,临时人员在不同时刻被摧毁,而不是在完全结束时 表达。第一个上下文是调用默认构造函数来初始化数组的元素。如果 构造函数有一个或多个默认参数,破坏默认情况下创建的每个临时值 在构造下一个数组元素之前,参数是按顺序排序的。
C ++标准版n3337 § 12.3 / 5
第二个上下文是引用绑定到临时的。 (...)
答案 1 :(得分:2)
g()
是暂时的。在评估整个完整表达式的整个时间内(在您的情况下,这将是f(g().c_str())
),temptence的生命周期会延长。因此,除非f()
,否则您的使用是安全的将指针存储在某处。
§12.2/ 4有两种情况下,临时表在不同于完整表达结束时被摧毁。第一个上下文是表达式作为定义对象的声明符的初始值设定项。在该上下文中,保存表达式结果的临时值将持续存在,直到对象的初始化完成。 [...]
§12.2/ 5第二个上下文是指引用绑定到临时。 [...]
这两种情况都不适用于您的示例。
答案 2 :(得分:2)
在评估包含表达式的完整表达式之后,构建作为表达式求值的一部分构造的临时对象,除非它绑定到命名引用。 (目前的标准草案中的12.2和1.9是相关部分)。
因此,在您的示例中,g
返回后,将保留用于保存f
返回值的临时构造。