在C ++中通过引用传递对象

时间:2013-08-09 12:48:49

标签: c++ class object syntax

在C ++(也是C)中通过引用传递变量的常用方法如下:

void _someFunction(dataType *name){ // dataType e.g int,char,float etc.
/****
definition
*/
}

int main(){
    dataType v;
    _somefunction(&v);  //address of variable v being passed
    return 0;
}

但令我惊讶的是,我注意到当通过引用传递对象时,对象本身的名称服务于目的(不需要&符号)并且在声明/定义函数期间没有参数前需要*符号。 以下示例应明确说明:

// this
#include <iostream>
using namespace std;

class CDummy {
  public:
    int isitme (CDummy& param);     //why not (CDummy* param);
};

int CDummy::isitme (CDummy& param)
{
  if (&param == this) return true;
  else return false;
}

int main () {
  CDummy a;
  CDummy* b = &a;
  if ( b->isitme(a) )               //why not isitme(&a)
    cout << "yes, &a is b";
  return 0;
}

我有问题理解为什么这个特殊的待遇是用课堂完成的。即使是几乎像一个类的结构也不会以这种方式使用。 是否将对象名称视为数组的地址?

5 个答案:

答案 0 :(得分:51)

似乎让您感到困惑的是,声明为引用传递的函数(使用&)不会使用实际地址调用,即&a

简单的答案是将函数声明为pass-by-reference:

void foo(int& x);

是我们所需要的。然后它会自动通过引用传递。

您现在可以像这样调用此函数:

int y = 5;
foo(y);

y将通过引用传递。

您也可以这样做(但为什么会这样?咒语是:尽可能使用引用,需要时使用指针):

#include <iostream>
using namespace std;

class CDummy {
public:
    int isitme (CDummy* param);
};


int CDummy::isitme (CDummy* param)
{
    if (param == this) return true;
    else return false;
}

int main () {
    CDummy a;
    CDummy* b = &a;             // assigning address of a to b
    if ( b->isitme(&a) )        // Called with &a (address of a) instead of a
        cout << "yes, &a is b";
    return 0;
}

输出:

yes, &a is b

答案 1 :(得分:12)

引用实际上是一个指针,含有足够的糖以使其味道很好......;)

但它也使用不同的指针语法,这使得使用引用比指针更容易。因此,在调用带有指针的函数时,我们不需要& - 编译器会为您处理。并且您不需要*来获取引用的内容。

要调用引用,别名是一个非常准确的描述 - 它是“同一事物的另一个名称”。因此,当a作为参考传递时,我们实际上是在传递a,而不是a的副本 - 它是通过传递a的地址完成的(内部) ,但你不必担心它是如何工作的[除非你正在编写自己的编译器,但是在编写自己的编译器时还需要​​了解很多其他有趣的事情,你不需要担心当你只是编程]。

请注意,引用对intclass类型的工作方式相同。

答案 2 :(得分:2)

在上述情况下通过引用传递只是实际对象的alias

您将使用不同的名称来引用实际对象。

references相比,pointer references提供了许多优势。

答案 3 :(得分:1)

好吧,好吧,你似乎混淆了pass-by-reference和pass-by-value。此外,C和C ++是不同的语言。 C不支持传递引用。

以下是两个按值传递的C ++示例

// ex.1
int add(int a, int b)
{
    return a + b;
}

// ex.2
void add(int a, int b, int *result)
{
    *result = a + b;
}

void main()
{
    int result = 0;

    // ex.1
    result = add(2,2); // result will be 4 after call

    // ex.2
    add(2,3,&result); // result will be 5 after call
}

当调用 ex.1 时,常量22将通过在堆栈中创建它们的本地副本来传递给函数。当函数返回时,弹出堆栈,并且传递给堆栈上的函数的任何内容实际上都消失了。

同样的事情发生在 ex.2 中,除了这次,指向int变量的指针也在堆栈上传递。该函数使用此指针(它只是一个内存地址)来取消引用并更改该内存地址的值,以便“返回”结果。由于函数需要一个内存地址作为参数,因此我们必须为它提供一个,我们通过在变量&上使用result“address-of”运算符来实现。

以下是传递引用的两个C ++示例

// ex.3
int add(int &a, int &b)
{
    return a+b;
}

// ex.4
void add(int &a, int &b, int &result)
{
    result = a + b;
}

void main()
{
    int result = 0;

    // ex.3
    result = add(2,2); // result = 2 after call
    // ex.4
    add(2,3,result); // result = 5 after call
}

这两个函数与前两个示例具有相同的最终结果,但不同之处在于它们的调用方式以及编译器如何处理它们。

首先,让我们了解pass-by-reference的工作原理。在pass-by-reference中,通常编译器实现将在最终可执行文件中使用“指针”变量来访问引用的变量,(或者似乎是共识),但这不一定是真的。从技术上讲,编译器可以简单地直接替换引用变量的内存地址,我怀疑这比一般认为的更真实。因此,在使用引用时,它实际上可以生成更高效的可执行文件,即使只是轻微的。

接下来,显然在使用pass-by-reference时调用函数的方式与按值传递没有什么不同,其效果是您可以直接访问函数中的原始变量。这通过隐藏来自调用者的实现细节而具有封装的结果。缺点是你不能改变传入的参数而不改变函数之外的原始变量。在您希望性能改进不需要复制大对象但不想修改原始对象的函数中,请在引用参数前加const

最后,与指针变量不同,您无法在创建引用后更改引用,并且必须在创建时初始化它们。

希望我能涵盖所有内容,这一切都是可以理解的。

答案 4 :(得分:0)

我必须补充的一点是C中没有引用。

其次,这是语言语法约定。 &安培; - 是一个地址运算符,但它也意味着一个引用 - 全部取决于美国案例

如果有一些“引用”关键字而不是&amp;你可以写

int CDummy::isitme (reference CDummy param)

但这是C ++,我们应该接受它的优点和缺点......