传递参数的方法 - 值与引用vs指针?

时间:2011-12-25 02:39:24

标签: c++

与其他编程语言相比,C ++支持三种不同的参数传递:

  • 按价值
  • 参考
  • 按地址

我使用C#进行了很长时间的编程,从C#开发人员的角度来看,C ++让我很困惑。在C#中它很容易。只需定义您想要的内容并返回结果,而C ++则要复杂得多。在使用by valueby referenceor by address时是否有类似指南的内容?

3 个答案:

答案 0 :(得分:6)

传递引用和传递值之间的区别非常重要。当您通过值传递时,您实际上正在传递相关值的副本。无论函数发生什么,调用者中的值都将保持不变。所以,假设你有一个函数可以将一个函数添加到int并返回int

int addOne(int theNumber)
{
    theNumber += 1;
    return theNumber;
}

在这里,你正在经历价值。你会这样称呼它:

int a = 10;
int b = addOne(a);    // b gets 11, but a remains the same

如果你想通过引用传递,那么函数将如下所示:

int addOne(int &theNumber)
{
    theNumber += 1;
    return theNumber;
}

请注意,函数的主体保持不变。再一次,你这样称呼它:

int a = 10;
int b = addOne(a);    // b gets 11, but this time a is also changed to 11.

这里最大的区别是你将引用传递给a。它实际上是一种指向a的隐式指针,但您可以将其视为传递a本身。由于您传递a而不是a的值副本,a本身实际上会被函数更改。

第三种方式,传递地址,如下所示:

int addOne(int *theNumber)
{
    *theNumber = *theNumber + 1;
    return *theNumber;
}

这与参考版本的功能相同,但此处的指针是显式的。你这样使用它:

int a = 10;
int b = addOne(&a);    // b gets 11, but this time a is also changed to 11.

因此,在这种情况下,您显式传递a的地址,即指向a的指针。如果你习惯于只通过价值,这应该是熟悉的。这是您通过C语言和其他一些类似C语言的引用传递a的方法。它工作正常,但你必须自己做所有的指针。 C ++增加了通过引用传递语言的概念,使这一切变得更容易。

最后一种可能性是传递 const引用,这可以避免复制值,但禁止在被调用函数中更改它。如果函数采用const引用,则可以将其视为不更改参数的承诺(并且它是编译器将强制执行的承诺)。如果值超过几个字节,这将特别有用,因此如果可以的话,最好避免复制值。出于这个原因,对象通常由const引用传递。

因此,作为指南,当您不希望调用者传递的内容发生更改时,请传递值或const引用。如果您想要更改,请通过引用传递。除非你正在处理需要它的C库或其他代码,否则不要通过指针传递。

答案 1 :(得分:1)

按值传递参数会生成该参数的副本,该副本将在函数内部使用。在函数结束后,参数的修改将丢失:

e.g。 :

void f(int a);
[
    a = 25;
}

int main()
{
    int i = 10;
    f(i);
    cout<<i;   //the printed   value will be 10;
}

但如果您使用地址或参考,则不同:

void g(int &a)
{
    a = 25;
}

int main()
{
    int i = 10;
    g(i);
    cout<<i;  // the printed value is 25 

}

通过地址或引用传递参数的一个优点是参数不会完全复制到堆栈。

答案 2 :(得分:0)

当您传递自己定义的对象或其他库中的对象时,它会更加混乱/复杂。依赖限制问题是您可以转发声明一个类,而不实际包含标题,如:

 // #include "myclass.h"   // we **Don't** include it! Less code-bloat
 class MyClass;  // foward-declare it

 void MyFunction(  MyClass*  obj  ); 
 // good to go, define this in .cpp file. 
 // someone including **This** header won't have to include myclass.h

 void MyFunction( MyClass& obj ); // Not Legal! 
 void MyFunction( MyClass obj ); // Not Legal! 
 void MyFunction( const MyClass& obj ); // Not Legal! 

我尝试使用“const MyClass&amp; obj”约定,但有时它是不可能的,因为库阻止了这种模式。如果你开始使用,我建议你按价值传递“int”,“double”等内容,不要担心。将未更改的标准模板对象传递为“const std :: Class&amp; amp; var',让你的函数返回东西而不是通过引用修改。

如果您的代码符合您的要求并且您担心性能,或者您使用的库需要它,请重新考虑该方法。