在临时之前调用的析构函数应该超出范围
destructor called before temporary should be out of scope
我有一段代码在VS2015下失败,但在GCC下可以工作。我很确定这个错误是Visual Studio造成的,但我想确保我对decltype(auto)的理解是正确的。
#include <iostream>
using namespace std;
string zero_params()
{
return "zero_params called.";
}
template< typename F >
auto test1( F f ) -> decltype(auto)
{
return f();
}
int main() {
cout << std::is_rvalue_reference< decltype(test1(zero_params)) >::value << endl;
cout << test1(zero_params) << endl;
cout << "Done!" << endl;
return 0;
}
在VisualStudio中,zero_params返回的字符串被推断为右值引用。此外,该对象的析构函数在test1()中被调用,调用f的返回发生在这里(这似乎是析构函数a&&对象的合理位置)。
在GCC下,返回的字符串不会被推断为右值引用。正如我所期望的那样,析构函数在cout语句中使用后被调用。
在Visual Studio中将返回类型指定为"string"而不是decltype(auto)可以修复此问题,在test1中对f()的返回使用remove_reference_t也是如此。
我的期望是GCC是正确的,因为zero_params()的函数签名是字符串,而不是字符串&;因此,如果它使用decltype(auto),我希望非引用"冒泡"到test1的返回类型。
这是一个正确的评估吗?
后期编辑:
我发现用VS2015解决这个问题的另一种方法是将给定给test1的函数封装在lambda:中
cout << test1(zero_params) << endl;
至:
cout << test1( [](auto&&... ps) { return zero_params(std::forward<decltype(ps)>(ps)...); } ) << endl;
因此,根据评论,我们可以得出结论:
- 这是VS2015预览中的一个错误
- 有变通办法
- 已报告错误
错误在于:
- 编译器应该将返回类型推导为字符串
- 它实际上推断它是字符串&
- 因此,它过早地破坏了价值
解决方法有:
- 不要对函数的返回类型使用decltype(auto)
- 在传入函数之前,将其包装在lambda表达式中
相关文章:
- 什么时候调用组成单元对象的析构函数
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 内联映射初始化的动态atexit析构函数崩溃
- 什么时候调用析构函数
- 优先顺序:智能指针和类析构函数
- C++-明确何时以及如何调用析构函数
- 使用基类指针创建对象时,缺少派生类析构函数
- 在c++中使用向量时,如何调用构造函数和析构函数
- 重载运算符new[]的行为取决于析构函数
- 对象析构函数在多线程处理时不断被调用,但该对象并未超出范围
- 对象超出范围后未调用析构函数
- C++:在析构函数超出范围之前调用析构函数
- 在临时之前调用的析构函数应该超出范围
- 对变量范围感到困惑 - 析构函数意外调用
- 为什么析构函数在对象引用作为参数传递时函数范围结束后调用
- 分段析构函数中的超出范围故障
- C++:在对象范围外调用析构函数
- 块范围静态的析构函数可以调用多次
- 在C++中,如果我引用一个具有解除分配析构函数~MyClass的对象,那么超出范围的引用会调用析构函数吗
- 当类的指针实例超出范围时不调用析构函数是真的吗?