【问题标题】:C++: when object constructed in argument is destructed?C++:当参数中构造的对象被破坏时?
【发布时间】:2014-08-12 08:48:17
【问题描述】:

当参数中构造的对象被破坏时,函数调用之前还是之后?

例如下面的代码安全吗?

void f(const char*)
{ ... }

std::string g()
{ ... }
...
f(g().c_str());

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

【问题讨论】:

  • 而不是使用 g().data() 使用 g().c_str(),只是一个想法......
  • @jamolnng 这对手头的问题没有影响。
  • 后来我才意识到,这就是我纠正它以添加相关信息的地方
  • @jamolnng 我修好了,data() 没有空终止符。

标签: c++


【解决方案1】:

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

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

C++ 标准 n3337 § 12.3/3

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

C++ 标准 n3337 § 12.3/4

在两种情况下,临时对象在与完整结束时不同的点被销毁- 表达。第一个上下文是调用默认构造函数来初始化数组元素时。如果 构造函数有一个或多个默认参数,销毁每个临时创建的默认参数 参数在构造下一个数组元素(如果有)之前排序。

C++ 标准 n3337 § 12.3/5

第二个上下文是引用绑定到临时的。 (...)

【讨论】:

  • 不,这不是未定义的行为。 g() 返回的本地 std::string 在评估完整表达式后被破坏。这意味着它直到 函数被调用后才会被破坏。
  • @0x499602D2 你的意思是g()临时返回的吗?
【解决方案2】:

g() 是临时的。 tempraries 的生命周期会在整个 full-expression 的整个评估时间内延长(在您的情况下,这将是 f(g().c_str()))因此您的使用是安全的,除非 f() 将指针存储在某处.

§12.2/4 有两种上下文,其中临时对象在与完整表达式结尾不同的点被销毁。第一个上下文是当表达式作为定义对象的声明符的初始值设定项出现时。在这种情况下,保存表达式结果的临时变量将持续存在,直到对象的初始化完成。 [...]

§12.2/5 第二个上下文是引用绑定到临时的。 [...]

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

【讨论】:

  • 这是正确的引用而不是 12.3/3 应该被引用吗?
  • @bits_international 我相信你的引用更好,因为它直接确认了临时寿命,而我的只是间接的。
【解决方案3】:

作为表达式评估的一部分构造的临时对象在评估包含该表达式的完整表达式后会被破坏,除非它绑定到命名引用。 (当前草案标准中的12.2和1.9是相关部分)。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-17
    • 2015-05-12
    • 2021-07-07
    • 2022-01-15
    • 2013-09-27
    • 2019-07-11
    • 2010-12-25
    • 2016-07-14
    相关资源
    最近更新 更多