C++ 为什么通过 const 引用而不是通过值传递?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2582797/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:00:20  来源:igfitidea点击:

Why pass by const reference instead of by value?

c++function

提问by Maulrus

From what I understand: when you pass by value, the function makes a local copy of the passed argument and uses that; when the function ends, it goes out of scope. When you pass by const reference, the function uses a reference to the passed argument that can't be modified. I don't understand, however, why one would choose one over the other, except in a situation where an argument needs to be modified and returned. If you had a void function where nothing is getting returned, why choose one over the other?

据我了解:当您按值传递时,该函数会生成传递参数的本地副本并使用它;当函数结束时,它超出范围。当您通过 const 引用传递时,该函数使用对无法修改的传递参数的引用。然而,我不明白为什么一个人会选择一个而不是另一个,除非在需要修改和返回参数的情况下。如果您有一个没有返回任何内容的 void 函数,为什么要选择一个?

EDIT: So basically passing by const reference avoids copying the object. So in what situations is copying the object good? I mean, why not just use const references all the time if it optimizes performance all the time?

编辑:所以基本上通过 const 引用传递避免了复制对象。那么在什么情况下复制对象好呢?我的意思是,如果它一直优化性能,为什么不一直使用 const 引用呢?

回答by CB Bailey

There are two main considerations. One is the expense of copying the passed object and the second is the assumptions that the compiler can make when the object is a a local object.

主要有两个考虑。一是复制传递对象的费用,二是当对象是本地对象时编译器可以做出的假设。

E.g. In the first form, in the body of fit cannot be assumed that aand bdon't reference the same object; so the value of amust be re-read after any write to b, just in case. In the second form, acannot be changed via a write to b, as it is local to the function, so these re-reads are unnecessary.

例如,在第一种形式中,在f它的主体中不能假定ab不引用同一个对象;所以在对a进行任何写入后必须重新读取的值b,以防万一。在第二种形式中,a不能通过写入来改变b,因为它是函数的本地,所以这些重新读取是不必要的。

void f(const Obj& a, Obj& b)
{
    // a and b could reference the same object
}

void f(Obj a, Obj& b)
{
    // a is local, b cannot be a reference to a
}

E.g.: In the first example, the compiler may be able to assume that the value of a local object doesn't change when an unrelated call is made. Without information about h, the compiler may not know whether an object that that function has a reference to (via a reference parameter) isn't changed by h. For example, that object might be part of a global state which is modified by h.

例如:在第一个示例中,编译器可能能够假设本地对象的值在进行无关调用时不会更改。如果没有关于 的信息h,编译器可能不知道该函数引用的对象(通过引用参数)是否没有被 更改h。例如,该对象可能是由 修改的全局状态的一部分h

void g(const Obj& a)
{
    // ...
    h(); // the value of a might change
    // ...
}

void g(Obj a)
{
    // ...
    h(); // the value of a is unlikely to change
    // ...
}

Unfortunately, this example isn't cast iron. It is possible to write a class that, say, adds a pointer to itself to a global state object in its constructor, so that even a local object of class type mightbe altered by a global function call. Despite this, there are still potentially more opportunities for valid optimizations for local objects as they can't be aliased directly by references passed in, or other pre-existing objects.

不幸的是,这个例子不是铸铁的。可以编写一个类,例如,在其构造函数中将指向自身的指针添加到全局状态对象,这样即使是类类型的局部对象也可能被全局函数调用更改。尽管如此,仍然有更多的机会对本地对象进行有效优化,因为它们不能被传入的引用或其他预先存在的对象直接别名化。

Passing a parameter by constreference should be chosen where the semantics of references are actually required, or as a performance improvement only if the cost of potential aliasing would be outweighed by the expense of copying the parameter.

const在实际需要引用语义的情况下,应选择通过引用传递参数,或者仅当潜在别名的成本被复制参数的成本所抵消时才作为性能改进。

回答by Georg Fritzsche

Passing arguments by value and thus copying them can be expensive - const references avoid that expensive step while still promising the caller that the object won't be changed.

按值传递参数并因此复制它们可能很昂贵——const 引用避免了这个昂贵的步骤,同时仍然向调用者保证对象不会被更改。

Usually fundamental types (int, double, ...) are passed by value, while class-types are passed by const reference.

通常基本类型 ( int, double, ...) 通过值传递,而类类型通过 const 引用传递。

There can however be exceptionswhere pass-by-value for class-types can be beneficial.

然而,在某些情况下,类类型的按值传递可能是有益的。

回答by Kirill V. Lyadvinsky

Making a copy of an object could greatly affect the performance in some cases. Consider a function which argument will be std::vector<long>and you want to pass vector with 1 million elements. In this case you'll want to use const reference over passing by value. In this SO question you could find simple general rule for your question.

在某些情况下,复制对象可能会极大地影响性能。考虑一个参数将是的函数,std::vector<long>并且您希望传递具有 100 万个元素的向量。在这种情况下,您将需要使用 const 引用而不是按值传递。在this SO question中,您可以为您的问题找到简单的一般规则。

回答by Dovi Salomon

An array can't be passed by value, so this is a good time to use a const pointer.

数组不能按值传递,因此这是使用 const 指针的好时机。

回答by Dean Harding

Sometimes, making a copy of an object can be expensive and so pass-by-const-reference will avoid having to make that copy. Otherwise, I would say that you should simply pass-by-value if that is what is semantically required.

有时,制作对象的副本可能很昂贵,因此传递常量引用将避免必须制作该副本。否则,我会说你应该简单地传递值,如果这是语义上的要求。

回答by Paolo Tedesco

To avoid making an unnecessary copy, thus improving performance.

为了避免不必要的复制,从而提高了性能。

回答by pmr

Passing an argument by value has the overhead of a copy of the object being passed to the function.

按值传递参数具有传递给函数的对象副本的开销。

Maybe an object isn't copyable and your choices are limited.

也许一个对象是不可复制的,你的选择是有限的。

回答by Naveen

Because of the performance benefits you will get. Lets say you have a big object (in terms of size in bytes). Now, if you pass this object by value to a function a unnecessary copy needs to be created of this, however you can get the same effect by passing a const reference to that object itself without creating copy. Since a reference is normally stored as a pointer under the hoods, the cost of passing a reference is just sizeof(pointer).

因为您将获得性能优势。假设您有一个大对象(以字节为单位的大小)。现在,如果您按值将此对象传递给函数,则需要为其创建一个不必要的副本,但是您可以通过向该对象本身传递常量引用而不创建副本来获得相同的效果。由于引用通常作为指针存储在引擎盖下,因此传递引用的成本仅为sizeof(pointer).