I/O 操纵器错误或临时延长寿命由 const 参考?
I/O manipulator bug or temporary lifetime extension by const ref?
我试图包装io操纵器std::put_money
。 下面是一个简化的插图:
#include <iomanip>
#include <iostream>
long double scale(long double f) { return f * 100.0L; }
namespace acm {
auto put_money(const long double &f, bool intl = false) {
return std::put_money(scale(f), intl);
}
}
int main() {
long double f(1234.567L);
std::cout << "1: " << acm::put_money(f) << 'n';
std::cout << "2: " << std::put_money(scale(f)) << 'n';
return 0;
}
输出为:
1: -92559631349317829570406876446720000000000000000000000000000000
2: 123457
我深入研究了 MSVC 和 libc++ 的胆量,了解到std::put_money
返回一个自定义类型,该类型保留对值的const 引用,而不是制作副本。
第 1 行可能是错误的,因为在流式传输自定义对象时引用无效(即,scale
在我的acm::put_money
中返回的临时值已被破坏(。
问:但是,为什么第2行是正确的?
理论1:"运气不好。 保留对临时的 const 引用是一个错误,但碰巧该值仍然存在于堆栈上,可能是因为它没有被额外的函数调用践踏。 (发布版本通常有效这一事实支持这一点,大概是因为额外的函数调用是内联的。
理论 2:通过 const 引用延长临时的寿命在第二种情况下有所帮助,但由于某种原因,它不适用于第一种情况。 也许额外的函数调用违反了延长寿命的规则?
理论3:???
最后位于标准中指定的位置(为了可读性而略微编辑(:
[分机]
template <class moneyT> unspecified put_money(const moneyT& mon, bool intl = false);
Requires:
moneyT
型应为长双 或basic_string
模板的专业化。
Returns:
未指定类型的对象,如果 out 是类型的对象 basic_ostream,表达式out << put_money(mon, intl)
表现为格式化的输出函数,调用f(out, mon, intl)
,其中函数f
定义为:[ 示例省略 ]
表达式
out << put_money(mon, intl)
应具有类型 basic_ostream和价值out
.
它的长短是,只有当std::put_money
位于<<
格式的输出运算符的右侧时,左侧是std::basic_ostream
时才定义。只有第 2 行满足该要求,第 1 行不符合。
- 不能使这种类型的"void(C::* volatile)(int) const "在参考手册C++示
- I/O 操纵器错误或临时延长寿命由 const 参考?
- RVALUE参考与const lVALUE参考作为参数之间的混淆
- 为什么const rvalue合格的std ::可选:: value()返回const rvalue参考
- 转发模板参数的const-度,我应该使用转发参考
- 如何检查两种类型是否相同,忽略const和参考
- 基于范围的循环中的const参考不起作用
- const自动参考绑定到(NULL)指针 - 实际类型是什么
- "const"会取消通用参考的资格吗?
- 重新分配到const参考
- 通过参考const成员通过参考时,尝试引用已删除的函数
- 人们为什么写私人场getters返回非const参考
- const参考的不同风味
- const参考变量初始化
- 分配给非const参考
- 类初始化的const参考
- C :TypeID忽略了低级别的const参考,而不是指针
- const参数与C 模板中的非const参考结合
- 临时对象和非const参考
- const参考和虚拟模板继承