简体   繁体   English

在临时之前调用的析构函数应该超出范围

[英]destructor called before temporary should be out of scope

I have a bit of code which fails under VS2015, but works under GCC. 我有一些代码在VS2015下失败,但在GCC下工作。 I'm pretty sure the bug is with Visual Studio but want to be sure that my understanding of decltype(auto) is correct. 我很确定这个bug是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;
}

Under Visual Studio the string returned by zero_params is deduced to be an rvalue reference. 在Visual Studio下,zero_params返回的字符串被推导为右值引用。 Furthermore the destructor of that object is called inside test1() where the return from the call to f happens (which seems a reasonable place to destruct a && object). 此外,该对象的析构函数在test1()中调用,其中从f调用返回f(这似乎是破坏&&对象的合理位置)。

Under GCC the string returned is not deduced to be an rvalue reference. 在GCC下,返回的字符串不会被推断为右值引用。 The destructor is called after use in the cout statement as I'd expect. 正如我所期望的那样,在cout语句中使用后调用析构函数。

Specifying the return type to be 'string' instead of decltype(auto) under Visual Studio fixes it, as does using remove_reference_t on the return of f() inside test1. 在Visual Studio下将返回类型指定为'string'而不是decltype(auto)可以修复它,就像在test1中返回f()时使用remove_reference_t一样。

My expectation would be that GCC is correct as the function signature for zero_params() is string, not string&& so I would expect the non-reference to 'bubble up' to the return type of test1 if it uses decltype(auto). 我的期望是GCC是正确的,因为zero_params()的函数签名是字符串,而不是字符串&&所以如果它使用decltype(auto),我会期望非引用'冒泡'到test1的返回类型。

Is this a correct assessment? 这是正确的评估吗?


LATE EDIT: 晚编辑:

Another way I've found to get around this with VS2015 is to wrap the function given to test1 in a lambda: 我发现使用VS2015解决这个问题的另一种方法是将给定的函数包装在lambda中:

cout << test1(zero_params) << endl;

to: 至:

cout << test1( [](auto&&... ps) { return zero_params(std::forward<decltype(ps)>(ps)...); } ) << endl;

So based on the comments we can conclude: 因此, 根据评论我们可以得出结论:

The bug is that: 错误是:

  • The compiler should have deduced the return type to be string 编译器应该将返回类型推断为字符串
  • It actually deduced it to be string && 它实际上推断它是字符串&&
  • Thus it destroyed the value prematurely 因此它过早地破坏了价值

The workarounds are: 解决方法是:

  • Don't use decltype(auto) for the function's return type 不要将decltype(auto)用于函数的返回类型
  • Wrap the function in a lambda expression before passing it in 在将函数传入之前将函数包装在lambda表达式中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM