通过值/指针/参考澄清

时间:2014-07-17 09:05:24

标签: c++ c++11 pass-by-reference pass-by-value pass-by-pointer

我需要对值/指针/引用传递进行一次又一次的澄清。

如果我有一个变量,如

int SomeInt = 10;

我想把它传递给像

这样的函数
void DoSomething(int Integer)
{
    Integer = 1;
}

在我将SomeInt传递给DoSomething()的当前场景中,我希望SomeInt的值能够根据我们对DoSomething()内部的操作进行更新,并且在内存和性能上最有效,所以我&# 39; m不要复制变量?可以说以下哪个原型可以完成这项任务?

void DoSomething(int* Integer);
void DoSomething(int& Integer);

我如何将变量实际传递给函数?前两个原型有什么区别?

最后如果在类中使用函数

class SomeClass
{
    int MyInteger;

public:
    void ChangeValue(int& NewValue)
    {
        MyInteger = NewValue;
    }
};

如果我将一个整数传递给ChangeValue,当我传入的整数被删除时,这意味着当我尝试在类中使用MyInteger时它将不再可用吗?

谢谢大家的时间,我知道这是一个基本的问题,但我不断的解释让我更加困惑。

4 个答案:

答案 0 :(得分:4)

你的两个例子

void DoSomething(int* Integer);
void DoSomething(int& Integer);

将完成任务。在第一种情况下 - 使用指针 - 您需要使用DoSomething(&SomeInt);调用函数,在第二种情况下 - 使用引用 - 更简单为DoSomething(SomeInt);

推荐的方法是在足够的时候使用引用,只在必要时使用指针。

答案 1 :(得分:4)

从功能上讲,所有这三项工作都是:

  • 传递int将返回类型更改为int,以便您可以返回新值,用法:x = f(x);

    • 当您计划设置值 而无需读取初始值 时,使用像int DoSomething();这样的函数要好得多,这样调用者才可以说int x = f();而不必在之前的行上创建x,并且想知道/担心是否需要在通话之前将其初始化为任何内容。
  • 传递int&并将其设置在函数内,用法:int x; x = ? /* if an input */; f(x);

  • 传递int*并在函数内设置指向int,用法:int x; x = ?; f(&x);

  

对内存和性能最有效,所以我不会复制变量

鉴于C ++标准没有规定编译器应该如何实现引用,尝试推断它们的特性是有点可疑的 - 如果你关心将代码编译成汇编或机器代码并看看它是如何工作的特定的编译器(用于特定的编译器命令行选项等)。如果您需要经验法则,假设引用具有与指针相同的性能特征,除非分析或生成代码检查另有建议。

对于int,您可以预期上面的第一个版本不会比指针版本 慢,并且可能更快 ,因为{{1}参数可以在寄存器中传递和返回,而不需要内存地址。

如果/何时/其中by-pointer版本是 inlined ,那么可能更慢的“需要内存地址以便我们可以传递指针”/“必须取消引用访问指针” /更新值“可以优化指针传递版本的方面(如果您已要求编译器尝试),使两个版本具有相同的性能....

尽管如此,如果您需要提出这样的问题,我无法想象您正在编写代码,而这些代码是重要的优化选择,因此更好的目标是为您提供最干净,最直观和最强大的用法对于客户端代码...现在 - 是否可以修改int(您可能会忘记前导x = f(x);)或x =可能无法实现的f(x),或x(某些调用者可能认为他们可以通过f(&x)本身就是一个合理的问题,但与您的性能问题分开.FWIW,C ++ FAQ Lite建议引用这种类型的指针情况,但我个人拒绝其推理和结论 - 这一切都归结为熟悉任何一个约定,以及你需要传递nullptr指针值或指针值const是有效的哨兵的频率,这可能与你在你的场景中所希望的你可能修改我的暗示相混淆......这在很大程度上取决于你的编码风格,你使用的库,问题领域等。

答案 2 :(得分:0)

您可以使用其中之一。第一个原型的函数调用将是

DoSomething(&SomeInt);  

和第二个原型

DoSomething(SomeInt);  

答案 3 :(得分:0)

如前所述,你可以同时使用两者。

的优点
void DoSomething(int* Integer)
{
  *Integer=0xDEADBEEF;
}
DoSomething(&myvariable);

模式是,从调用中可以明显看出myvariable可能会发生变化。

的优点
void DoSomething(int& Integer)
{
  Integer=0xDEADBEEF;
}
DoSomething(myvariable);

模式是DoSomething中的代码更清晰,DoSomething更难以以糟糕的方式处理内存,并且您可能会从中获得更好的代码。缺点是,通过阅读调用myvariable可能会发生变化并不是很明显。