为什么变量会自动通过引用传递?

时间:2012-03-19 16:07:31

标签: c++

我试图在ROOT绘图包中调用一个接受三个变量的函数。我的代码中的相关部分是:

int xwidth=0,ywidth=0;
Bool_t useangle=0;
vIt->GetBoundingBox(xwidth,ywidth,useangle);

其中vIt是GetBoundingBox作为类成员函数的对象的迭代器。 (Bool_t只是ROOT使用的typedef。)

现在,当我编译时,我从g ++中得到以下错误:

error: no matching function for call to ‘TText::GetBoundingBox(int&, int&, Bool_t&)’
/home/bwhelan/Programs/MODIFIED//External/root/5.30.00/include/root/TText.h:57: note:   candidates are: virtual void TText::GetBoundingBox(UInt_t&, UInt_t&, Bool_t)

我的问题是为什么在这里通过引用传递useangle而不是值?我根本想不出来。

4 个答案:

答案 0 :(得分:8)

在C ++中,在重载解析时,会选择一组可行的重载,以及需要最少的一个候选 转换(它是否需要更改const??是否需要提升整数到浮点?) 被选中。如果有多个具有相同权重的匹配项,则调用模糊不清并收到错误 (例如:int foo(int &x, int y); int foo(int x, int &y); ... int a,b; foo(a,b);含糊不清)。

但是,在您的情况下,找不到有效的转换序列,因为没有有效的转换 int&unsigned int&(旁注:存在从intunsigned int的转换,反之亦然),因为 对不相关类型的引用完全不兼容。

关于错误消息:编译器使用最弱的允许绑定来过滤掉可行功能集。对于int,这是int&。 但由于找不到可行的函数集,因此会出现错误消息。消息的作者没有基础 它在你的代码上,而是在他/她搜索的数据上,int&。但是,他/她 正确地提出了一个真正存在的可行替代方案。

所以我们在这里有更多的编译器诊断质量问题,而不是C ++ 正确性问题。


从标准来看,这是转换表。进行函数调用至少需要 有效,匹配越好:

Conversion                         
-----------------------------------+----------------------------
No conversions required            | Identity
-----------------------------------+----------------------------
Lvalue-to-rvalue conversion        | Lvalue transformation
Array-to-pointer conversion        |
Function-to-pointer conversion     |
-----------------------------------+----------------------------
Qualification conversions          | Qualification adjustment
-----------------------------------+----------------------------
Integral promotions                | Promotion
Floating point promotion           |
-----------------------------------+----------------------------
Integral conversions               | Conversion
Floating point conversions         |
Floating-integral conversions      |
Pointer conversions                |
Pointer to member conversions      |
Boolean conversions                |
-----------------------------------+----------------------------

答案 1 :(得分:3)

问题不在于bool是通过引用传递的,而是你行

int xwidth=0,ywidth=0;

应为UInt_t

类型
UInt_t xwidth=0u,ywidth=0u;

编译器不知道你想如何传递变量以使用unkown重载来运行,所以它只是假设你的意思是参考。

答案 2 :(得分:2)

该函数的签名具有以下参数

UInt_t&, UInt_t&, Bool_t

你正在传递

int&, int&, Bool_t&

在调用方法之前将int转换为UInt_t或直接将其声明为UInt_t

答案 3 :(得分:1)

不是。

编译器消息或多或少有用。实际上,由于它没有找到可以使用您提供的参数调用的方法,因此编译器正在尝试从您提供的参数中合成一个可能有效的方法签名。

不幸的是,这最终注定要失败,因为有太多可能的变化,但gcc的消息从未如此强大。

Clang采取了另一种方法,我更喜欢这种做法。而不是试图想象你想要调用的函数是什么样的,然后列出候选者并让你发现差异,它会告诉你为什么每个候选人都被丢弃了。

void func(unsigned&, unsigned&);

int something() {
  int a = 0, b = 0;
  func(a, b);
  return a + b;
}

产生以下错误消息:

/tmp/webcompile/_3246_0.cc:5:3: error: no matching function for call to 'func'
  func(a, b);
  ^~~~
/tmp/webcompile/_3246_0.cc:1:6: note: candidate function not viable:
    no known conversion from 'int' to 'unsigned int &' for 1st argument; 
void func(unsigned&, unsigned&);

我发现它更有用。通过将a转换为unsigned并离开b来修补此问题:

/tmp/webcompile/_3710_0.cc:1:6: note: candidate function not viable:
    no known conversion from 'int' to 'unsigned int &' for 2nd argument; 
void func(unsigned&, unsigned&);

这样我们一次推进一个参数,直到我们“调整”我们喜欢的电话。