8

例如:

int StrLen(const std::string &s = "default string") {
  const std::string &t = "another string";  // BTW, is this line safe?
  return s.size();
}

更新

SoapBox 的结论是正确的,但原因并不完全正确。

临时对象的生命周期会自动延长到与持有它的引用相同。

这通常是正确的,但有几个例外。一个是

“在函数调用中临时绑定到引用参数会一直持续到包含调用的完整表达式完成为止。”

我认为这个例外适用于默认参数情况。

另一个例外与 SoapBox 回答中的附加示例有关:

“临时绑定到函数返回语句中的返回值的生命周期不会延长;临时在返回语句中的完整表达式结束时被销毁。”

4

3 回答 3

5

是的,这两件事都是安全的。它们构造临时对象,并且临时对象的生命周期自动延长到与持有它的引用相同。

虽然我们正在讨论这个主题,但这是不安全的临时人员的常见错误

std::string const &accessor() const {
    if (my_name_is_valid())
        return m_my_name;
    else
        return "";
}

这是无效的,因为临时是在accessor函数内部创建的,然后返回对它的引用。调用者将收到对已破坏对象的引用……这是未定义的行为,通常会导致崩溃。

于 2012-07-20T01:07:01.497 回答
3

SoapBox 的回答是正确的,但是限制是什么并不总是很明显。

这通常是正确的,但有几个例外。一个是“在函数调用中临时绑定到引用参数的情况一直存在,直到包含调用的完整表达式完成”。我认为这个例外适用于默认参数情况。

它确实,虽然有时以微妙的方式,考虑这两个例子:

struct A { A(std::string const& s): _ref(s) {} std::string const& _ref; };

struct B { B(std::string s): _ref(s) {} std::string const& _ref; };

在这两个示例中,函数都是构造函数。

  • In A: 临时的生命周期被延长到完整表达式的结尾意味着A a("Hello"); std::cout << a._ref << "\n";不安全。暂时只活到了第一个;
  • In B: 参数本身是一个临时的,这里根本没有绑定到 const-reference。一个好的编译器会发出警告。

另一个例外与 SoapBox 回答中的附加示例有关:“临时绑定到函数返回语句中的返回值的生命周期没有延长;临时在返回语句中的完整表达式结束时被销毁。”

这源于该return语句的一般工作方式。就标准而言,下面有两个副本正在进行中。那是:

  1. 调用return会将结果复制到“结果槽”中
  2. 如果有的话,调用者会将“结果槽”中的值复制到其存储中。

当然,副本可以被优化掉(复制省略),但这很重要,因为临时对象的生命周期只会扩展到它绑定到的原始常量引用。如果该引用的副本超过了原始引用的生命周期,则它指的是垃圾,这就是return语句中发生的情况。

于 2012-07-20T06:57:45.610 回答
-4

是的。该字符串被分配为静态文本,不会移动或更改。

于 2012-07-20T01:06:01.523 回答