与其他编程语言相比,C ++支持三种不同的参数传递:
我使用C#进行了很长时间的编程,从C#开发人员的角度来看,C ++让我很困惑。在C#中它很容易。只需定义您想要的内容并返回结果,而C ++则要复杂得多。在使用by value
,by reference
,or by address
时是否有类似指南的内容?
答案 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',让你的函数返回东西而不是通过引用修改。
如果您的代码符合您的要求并且您担心性能,或者您使用的库需要它,请重新考虑该方法。