【问题标题】:Destruction of string temporaries in thrown exceptions在抛出的异常中销毁临时字符串
【发布时间】:2011-01-25 20:28:28
【问题描述】:

考虑以下代码:

std::string my_error_string = "Some error message";

// ...

throw std::runtime_error(std::string("Error: ") + my_error_string);

传递给runtime_error 的字符串是字符串operator+ 返回的临时字符串。假设这个异常被处理如下:

catch (const std::runtime_error& e)
{
    std::cout << e.what() << std::endl;
}

string的operator+返回的临时值什么时候销毁?语言规范对此有什么要说的吗?另外,假设 runtime_error 接受了 const char* 参数并被抛出如下:

// Suppose runtime_error has the constructor runtime_error(const char* message)
throw std::runtime_error((std::string("Error: ") + my_error_string).c_str());

现在operator+返回的临时字符串什么时候销毁?它会在 catch 块尝试打印它之前被销毁吗,这就是为什么 runtime_error 接受 std::string 而不是 const char* 的原因吗?

【问题讨论】:

  • Nitpick: std::runtime_error("Error: " + my_error_string); 很好,因为 my_error_string 是字符串类型。您不必在 "Error: " 上显式调用 std::string 构造函数并弄乱您的代码。
  • 我更喜欢std::string("Error: ").append(my_error_string)

标签: c++ exception destructor temporary


【解决方案1】:

runtime_error 是一个包含字符串的类。该字符串将由正常的 C++ 构造和销毁机制为您管理。如果它包含一个 char *,那么它必须被显式管理,但作为 runtime_error 的用户,你仍然不需要做任何事情。

尽管您可能在 Internet 上的其他地方看到了什么,但 C++ 的设计几乎总是做“合理的事情”——您实际上必须相当努力地打破这种合理的行为,当然这并非不可能。

【讨论】:

  • 回答销毁问题:一旦std::runtime_error 对象存在(即其构造函数成功终止),创建的临时对象就会被销毁。当然,对象有它的副本,所以没关系;)
【解决方案2】:

作为临时对象 (12.2),+ 的结果将作为评估包含它的 完整表达式 (1.9/9) 的最后一步被销毁。在这种情况下,full-expressionthrow-expression

throw-expression 构造一个临时对象(exception-object)(15.1)(在这种情况下为std::runtime_error)。 throw-expression 中的所有临时对象将在 exception-object 构造完成后销毁。只有在 throw-expression 的评估完成后才会抛出异常,因为临时对象的销毁是此评估的一部分,它们将在销毁自进入 try 块以来构建的自动变量之前被销毁(15.2) 以及在进入处理程序之前。

runtime_error 的构造函数的后置条件是what() 返回的东西strcmp 认为等于传入参数返回的c_str()。理论上的可能性是,一旦作为构造函数参数传递的std::string 被销毁,runtime_errorwhat() 可能会返回不同的东西,尽管这将是一个有问题的实现并且它仍然必须是一个空终止某种字符串,它无法返回指向死字符串的陈旧c_str() 的指针。

【讨论】:

    【解决方案3】:

    请注意,runtime_error 异常类会复制传递给构造函数的字符串。因此,当您在异常对象上调用 .what() 时,您不会返回您传入的完全相同的字符串实例。

    因此,为了回答您的问题,您要询问的临时变量在包含它的表达式的“分号”处被破坏(在您的第一个和第二个问题版本中都是如此),但正如我所说,这不是很有趣,因为它已经复制了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多