临时人员的 C++ 生命周期 - 这安全吗?
Posted
技术标签:
【中文标题】临时人员的 C++ 生命周期 - 这安全吗?【英文标题】:C++ lifetime of temporaries - is this safe? 【发布时间】:2014-11-07 03:00:40 【问题描述】:如果我正确理解了临时对象的生命周期规则,那么这段代码应该是安全的,因为 make_string()
中的临时 stringstream
的生命周期一直持续到完整表达式的末尾。我不是 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");
【问题讨论】:
在我看来应该没问题。 技术上没问题,但我相信你会发现它相当低效。考虑使用operator<<
定义一个字符串构建器。
@Cheersandhth.-Alf 取决于编译器内联的积极程度。
@cdhowie:不,我在想stringstream
。应该是ostringstream
,但这无济于事。问题是它对语言环境的支持非常普遍,所以,它通常很慢。
这可行,但为了便于阅读,我倾向于在make_string()
中使用以下内容:ostringstream s; make_string_impl(s, ts...); return s.str();
。它没有那么聪明,但它可以让你在make_string_impl()
中使用ostringstream&
,这意味着你可以省略std::move()
的讨厌——只是传递一个引用。然后make_string_impl()
也可以返回void
。更容易阅读,更容易让编译器内联。它还回避了您对该技术安全性的疑问。
【参考方案1】:
标准的相关部分在§12.2
:
12.2.3) 临时对象作为最后一步被销毁 在评估完整表达式(1.9)时(词法上)包含它们被创建的点。
除了:
12.2.4) 有两种上下文,其中临时对象在与完整表达式结尾不同的点被销毁。第一个上下文是调用默认构造来初始化数组元素时。 ... [不适用]
12.2.5) 第二个上下文是引用绑定到临时的。引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的生命周期内持续存在,除了:
...
在函数调用 (5.2.2) 中临时绑定到引用参数会一直存在,直到包含调用的完整表达式完成为止。
所以你去。临时的stringstream
绑定到函数调用中的引用,因此它会一直持续到表达式完成。这是安全的。
【讨论】:
谢谢,这看起来很确定:)以上是关于临时人员的 C++ 生命周期 - 这安全吗?的主要内容,如果未能解决你的问题,请参考以下文章