如果我理解正确的临时生命规则,这段代码应该是安全的,因为stringstream
中临时make_string()
的生命周期一直持续到完整表达式结束。我不是100%有信心这里没有一个微妙的问题,任何人都可以确认这种使用模式是否安全吗?它似乎在clang和gcc中工作正常。
#include <iomanip>
#include <iostream>
#include <sstream>
using namespace std;
ostringstream& make_string_impl(ostringstream&& s) { return s; }
template<typename T, typename... Ts>
ostringstream& make_string_impl(ostringstream&& s, T&& t, Ts&&... ts) {
s << t;
return make_string_impl(std::move(s), std::forward<Ts>(ts)...);
}
template<typename... Ts>
string make_string(Ts&&... ts) {
return make_string_impl(ostringstream{}, std::forward<Ts>(ts)...).str();
}
int main() {
cout << make_string("Hello, ", 5, " World!", '\n', 10.0, "\n0x", hex, 15, "\n");
}
答案 0 :(得分:7)
标准的相关部分位于§12.2
:
12.2.3)临时对象作为最后一步被销毁 在评估全表达式(1.9)时(词法上)包含创建它们的点。
除了:
12.2.4)有两种情况下,临时表在不同于完整表达结束时被销毁。第一个上下文是调用默认构造来初始化数组的元素。 ...... [不适用]
12.2.5)第二个上下文是指引用绑定到临时。引用绑定的临时值或作为绑定引用的子对象的完整对象的临时值在引用的生命周期内持续存在,除了:
...
在函数调用(5.2.2)中对引用参数的临时绑定一直持续到包含该调用的完整表达式完成为止。
所以你去吧。临时stringstream{}
绑定到函数调用中的引用,因此它将持续到表达式完成。这很安全。