【问题标题】:C++11 auto type deduction from arithmetic operation on int& and longC++11 对 int& 和 long 的算术运算的自动类型推导
【发布时间】:2016-12-14 09:52:56
【问题描述】:

我一定是误解了auto c++11 及更高版本如何解析类型。我有以下代码:

void foo(int& x)
{
    ++x;
}

int main()
{
    int i = 2;
    int& ir = i;
    long L = 5;
    auto a = ir/L;
    foo(a);

    return 0;
}

这会导致编译器错误:

test.cpp: In function 'int main()':

test.cpp:12:10: error: invalid initialization of non-const reference
of type ‘int&’ from an rvalue of type ‘int’
     foo(a);
          ^

test.cpp:1:6: note:   initializing argument 1 of ‘void foo(int&)’
 void foo(int& x)
      ^~~

但是,将 auto 替换为 int (int a = ir/L;) 可以正常编译并给出预期的结果(在调用 foo() 之前的 a == 0 和之后的 a == 1)。在玩弄代码并看到各种错误消息后,我认为auto 被推导出为long int&。定义函数void bar(int x)void bar(const int& x) 会导致错误消息:call of overloaded ‘bar(long int&)’ is ambiguous

来自 cmets 的更正:

我不明白auto x = [int&]/[int] 是如何产生一个可以由非常量引用传递的左值,而auto x = [int&]/[long] 产生一个不能被传递的右值。

【问题讨论】:

  • a 不是参考,它是一个简单的long
  • 如果你不明白为什么它很长,原因是类型提升。你应该read the answer to this
  • 我必须同意,如果没有错误,错误消息会产生误导。它应该是invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘long’。 VS2015的报错信息更有帮助:'void foo(int &)': cannot convert argument 1 from 'long' to 'int &'
  • 当您认为x 很长时,该错误非常有意义。要将其传递给需要int(或int&)的函数,需要创建一个临时(右值)int。而且它不能绑定到非常量引用。

标签: c++ c++11 reference c++14 auto


【解决方案1】:

ir/L 的结果是long。对于arithmetic operator,当二元运算符有不同类型时,产生的结果将是普通类型;在intlong 之间应该是long

所以auto a = ir/L;a 的类型是long。它不能传递给foo(int&),因为你不能将左值引用绑定到不同类型的非常量。

另一方面,鉴于L 的类型是int,那么对于auto a = ir/L;a 的类型将是int,那么一切都很好。

关于“错误的右值部分”,当您将long 传递给foo(int&) 时,首先编译器会尝试将其转换为int,这是一个临时的(即右值)并且可以'不被绑定到非常量的左值引用。

long 可以隐式转换为int,并且temporary 可以绑定到对const 的左值引用,因此将long 变量传递给bar(int x)bar(const int&) 就可以了。

顺便说一句:当您编写 int a = ir/L; 时,long 类型的结果会隐式转换为 int。所以你会得到一个int 然后将它传递给foo(int&) 就可以了。

【讨论】:

  • 我明白了。我从未考虑过创建临时值(错误消息中的右值)的类型转换。这很有意义。谢谢。
【解决方案2】:

您使用auto 的事实与此无关。

along 类型,由于参数提升的规则。

因为foo 采用参数通过引用,编译失败,因为int& 无法绑定到long 类型(即使它们的大小相同并且具有相同的补码表示) .

【讨论】:

  • int const& 会很好地绑定到临时缩小的int
  • @StoryTeller:绝对!
猜你喜欢
  • 2018-01-21
  • 2021-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-16
  • 1970-01-01
  • 2015-11-11
  • 2013-01-05
相关资源
最近更新 更多