简体   繁体   English

我应该在哪里更喜欢按引用传递或按值传递?

[英]Where should I prefer pass-by-reference or pass-by-value?

In what circumstances should I prefer pass-by-reference?在什么情况下我应该更喜欢按引用传递? Pass-by-value?价值传递?

There are five main cases where you should use pass-by-reference over pass-by-value:有五种主要情况您应该使用传递引用而不是传递值:

  1. If you are calling a function that needs to modify its arguments, use pass-by-reference as its the only way to get this effect (I treat pass-by-reference and pass-by-pointer interchangeably in this case, though with pass-by-pointer you often have to explicitly check for nullptr .)如果您正在调用需要修改其参数的函数,请使用传递引用作为获得此效果的唯一方法(在这种情况下,我将传递引用和传递指针互换地对待,尽管使用传递-by-pointer 你经常需要显式检查nullptr 。)
  2. If you're calling a function that needs to take a large object as a parameter, pass it by const reference to avoid making an unnecessary copy of that object and taking a large efficiency hit.如果您正在调用需要将大对象作为参数的函数,请通过 const 引用传递它,以避免对该对象进行不必要的复制并降低效率。
  3. If you're writing a copy or move constructor which by definition must take a reference, use pass by reference.如果您正在编写根据定义必须接受引用的复制或移动构造函数,请使用按引用传递。
  4. If you're writing a function that wants to operate on a polymorphic class, use pass by reference or pass by pointer to avoid slicing.如果您正在编写一个想要对多态类进行操作的函数,请使用按引用传递或按指针传递以避免切片。
  5. If you're writing a function that might return a very large or uncopyable object, use pass by reference as a way to use a parameter to store the produced value.如果您正在编写可能返回非常大或不可复制的对象的函数,请使用按引用传递作为使用参数存储生成值的方法。

There are several considerations, including:有几个考虑因素,包括:

Performance表现

Passing by value copies the data, so passing large data structures by value can inhibit performance.按值传递会复制数据,因此按值传递大型数据结构会抑制性能。 Passing by reference passes only a reference (basically the address) to the data.通过引用传递只传递一个对数据的引用(基本上是地址)。 For large data structures, this can greatly improve performance.对于大型数据结构,这可以大大提高性能。 For smaller data structures (like an int), passing by reference can inhibit performance.对于较小的数据结构(如 int),按引用传递会抑制性能。

Modifications修改

Passing by value copies the data so if the target code modifies that copy, it will not affect the original.按值传递会复制数据,因此如果目标代码修改了该副本,则不会影响原始数据。 Passing by reference passes only the address of the data, so modifications made against that reference will be "visible" to the calling code.通过引用传递仅传递数据的地址,因此针对该引用所做的修改将对调用代码“可见”。

Yes.是的。

Pass by value for things like native types that are small enough that passing them directly is efficient.对于像本机类型这样足够小的东西,直接传递它们是有效的,按值传递是有效的。 Otherwise use pass by ( const ) reference.否则使用 pass by ( const ) 引用。

The hard part is writing a template that could apply to either (in which case, you usually want to use pass by reference -- the potential penalty for passing a large object by value is much worse than the potential penalty for passing by reference when passing by value would have been preferred).困难的部分是编写一个可以适用于任何一个的模板(在这种情况下,您通常希望使用通过引用传递——通过值传递大对象的潜在惩罚比传递时通过引用传递的潜在惩罚要糟糕得多按价值将是首选)。

Edit: this, of course, is assuming a situation where the required semantics would allow either one -- obviously if you're working with something like polymorphic objects, there's no real "preference" involved, because you must use a pointer or reference to get correct behavior.编辑:这当然是假设所需的语义允许其中任何一个的情况 - 显然,如果您正在使用多态对象之类的东西,则不涉及真正的“偏好”,因为您必须使用指针或引用得到正确的行为。

As others already have replied to your question sufficiently well, I would like to add an important point:由于其他人已经很好地回答了您的问题,我想补充一点:

If the class does not have public copy-constructor, then you don't have choice to pass by value;如果该类没有public拷贝构造函数,那么你没有选择,按值传递; you have to pass by reference (or you can pass pointer).必须通过引用传递(或者你可以传递指针)。

The following program would not compile:以下程序无法编译:

class A
{
public:
     A(){}
private:
     A(const A&) {}
};

//source of error : pass by value
void f(A ) {}

int main() {
        A a;
        f(a);
    return 0;
}

Error:错误:

prog.cpp: In function 'int main()': prog.cpp:在函数“int main()”中:
prog.cpp:10: error: 'A::A(const A&)' is private prog.cpp:10: 错误:'A::A(const A&)' 是私有的
prog.cpp:18: error: within this context prog.cpp:18: 错误:在此上下文中
prog.cpp:18: error: initializing argument 1 of 'void f(A)' prog.cpp:18: 错误:初始化“void f(A)”的参数 1

See yourself at ideone : http://www.ideone.com/b2WLi在 ideone 上看到自己: http : //www.ideone.com/b2WLi

But once you make function f pass by reference, then it compiles fine : http://www.ideone.com/i6XXB但是一旦你让函数f通过引用传递,那么它编译得很好: http : //www.ideone.com/i6XXB

You have tagged your question with both C and C++.您已使用 C 和 C++ 标记了您的问题。

Therefore, I suggest that you consider using pass by reference in C++ which supports this feature and that you do not consider using it in C which does not support this feature.因此,我建议您考虑在支持此功能的 C++ 中使用按引用传递,而不要考虑在不支持此功能的 C 中使用它。

here's the simple rule:这是简单的规则:

pass by reference when the value is large.

the other answers are amazing.其他答案是惊人的。 Just trying to make this simplest.只是试图使这个最简单。

pass by reference can be called only in below conditions:只能在以下条件下调用通过引用传递:

Pass-by-references is more efficient than pass-by-value, because it does not copy the arguments.引用传递比值传递更有效,因为它不复制参数。 The formal parameter is an alias for the argument.形式参数是参数的别名。 When the called function read or write the formal parameter, it is actually read or write the argument itself.当被调用函数读或写形参时,实际上是读或写实参本身。

The difference between pass-by-reference and pass-by-value is that modifications made to arguments passed in by reference in the called function have effect in the calling function, whereas modifications made to arguments passed in by value in the called function can not affect the calling function.引用传递和值传递的区别在于,对被调用函数中按引用传入的参数所做的修改在调用函数中有效,而对被调用函数中按值传入的参数所做的修改不能影响调用函数。

Use pass-by-reference if you want to modify the argument value in the calling function.如果要修改调用函数中的参数值,请使用传递引用。 Otherwise, use pass-by-value to pass arguments.否则,使用按值传递来传递参数。

The difference between pass-by-reference and pass-by-pointer is引用传递和指针传递的区别是

that pointers can be NULL or reassigned whereas references cannot.指针可以为 NULL 或重新分配,而引用不能。 Use pass-by-pointer if NULL is a valid parameter value or if you want to reassign the pointer.如果 NULL 是有效的参数值或者您想重新分配指针,请使用传递指针。 Otherwise, use constant or non-constant references to pass arguments.否则,使用常量或非常量引用来传递参数。

While pointers are references, "reference" in c++ usually refers to the practice of tagging a parameter of SomeType&.虽然指针是引用,但 c++ 中的“引用”通常是指标记 SomeType& 参数的做法。

Which you should never do.你永远不应该做的。 The only place it is appropriate is as a magic syntax required to implement the various pre-defined operators.它唯一合适的地方是作为实现各种预定义运算符所需的魔法语法。 Otherwise:除此以外:

  • You should never pass out parameters by reference - pass by pointer, otherwise you make code reviews all but impossible.你永远不应该通过引用传递参数——通过指针传递,否则你几乎不可能进行代码审查。 Pass by reference makes it impossible to tell by examining a call which parameters can be expected to be changed.通过引用传递使得无法通过检查调用来判断哪些参数可能会被更改。

  • You should never pass in parameter by reference either.您也不应该通过引用传递参数。 Again, this means you are performing a meta optimization.同样,这意味着您正在执行元优化。 You should always just pass-by-value, otherwise you are guilty of peeking inside an object, examining its implementation and deciding that pass-by-reference is preferred for some reason.你应该总是只按值传递,否则你会偷看对象内部,检查它的实现并决定出于某种原因首选按引用传递。

Any c++ class should implement all the copy and assignment constructors and overloads necessary to be passed around by value.任何 c++ 类都应该实现按值传递所需的所有复制和赋值构造函数和重载。 Otherwise it has not done its job, of abstracting the programmer from the implementation details of the class.否则它就没有完成它的工作,即从类的实现细节中抽象出程序员。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 区分传递参考和传递价值 - Distinguishing Pass-by-Reference and Pass-by-Value C ++中按值传递和按引用传递之间的区别 - Differences between pass-by-value and pass-by-reference in c++ 区分函数模板中的值传递和引用传递 - Distinguish between pass-by-value and pass-by-reference in a function template 函数参数按值传递比按引用传递更快? - Function argument pass-by-value faster than pass-by-reference? 值传递和 std::move 优于传递引用的优点 - Advantages of pass-by-value and std::move over pass-by-reference 通过查看装配将值传递与引用传递性能进行比较 - Comparing pass-by-value with pass-by-reference performance by looking at assembly 如何获得模板参数包来推断按引用而不是按值? - How do I get a template parameter pack to infer pass-by-reference rather than pass-by-value? 我可以让C ++编译器决定是按值传递还是按引用传递? - Can I let the C++ compiler decide whether to pass-by-value or pass-by-reference? 将按引用传递和按值传递混合到可变参数模板函数是否有效? - Mixing pass-by-reference and pass-by-value to variadic template function valid? C++:赋值运算符:按值传递(复制和交换)与按引用传递 - C++: assignment operator: pass-by-value (copy-and-swap) vs pass-by-reference
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM