在c++中,是通过值传递更好,还是通过引用到const传递更好?
我不知道哪种做法更好。我意识到,通过引用传递到const应该在程序中提供更好的性能,因为您没有对变量进行复制。
在c++中,是通过值传递更好,还是通过引用到const传递更好?
我不知道哪种做法更好。我意识到,通过引用传递到const应该在程序中提供更好的性能,因为您没有对变量进行复制。
当前回答
这是我在设计非模板函数的接口时通常采用的方法:
Pass by value if the function does not want to modify the parameter and the value is cheap to copy (int, double, float, char, bool, etc... Notice that std::string, std::vector, and the rest of the containers in the standard library are NOT) Pass by const pointer if the value is expensive to copy and the function does not want to modify the value pointed to and NULL is a value that the function handles. Pass by non-const pointer if the value is expensive to copy and the function wants to modify the value pointed to and NULL is a value that the function handles. Pass by const reference when the value is expensive to copy and the function does not want to modify the value referred to and NULL would not be a valid value if a pointer was used instead. Pass by non-const reference when the value is expensive to copy and the function wants to modify the value referred to and NULL would not be a valid value if a pointer was used instead.
其他回答
编辑:戴夫·亚伯拉罕斯关于cpp-next的新文章:想要速度?按值传递。
对于复制容易的结构体,通过值传递还有一个额外的好处,即编译器可能假定对象没有别名(不是相同的对象)。使用引用传递,编译器不能总是这样假设。简单的例子:
foo * f;
void bar(foo g) {
g.i = 10;
f->i = 2;
g.i += 5;
}
编译器可以将其优化为
g.i = 15;
f->i = 2;
因为它知道f和g不在同一个位置。如果g是一个引用(foo &),编译器不可能假设。因为g.i可以用f->i作为别名,所以它的值必须是7。因此编译器必须从内存中重新获取g.i的新值。
对于更实用的规则,可以在Move Constructors文章(强烈推荐阅读)中找到一组很好的规则。
如果函数打算将实参作为副作用更改,则通过非const引用获取它。 如果函数没有修改其实参,且实参为基本类型,则按值获取它。 否则通过const引用获取,以下情况除外 如果函数无论如何都需要复制const引用,则按值获取。
"Primitive" above means basically small data types that are a few bytes long and aren't polymorphic (iterators, function objects, etc...) or expensive to copy. In that paper, there is one other rule. The idea is that sometimes one wants to make a copy (in case the argument can't be modified), and sometimes one doesn't want (in case one wants to use the argument itself in the function if the argument was a temporary anyway, for example). The paper explains in detail how that can be done. In C++1x that technique can be used natively with language support. Until then, i would go with the above rules.
示例:要使字符串大写并返回大写版本,应该始终通过value传递:无论如何都必须获取它的副本(不能直接更改const引用)-所以最好让它对调用者尽可能透明,并尽早复制,以便调用者尽可能优化-如论文中所述:
my::string uppercase(my::string s) { /* change s and return it */ }
然而,如果你不需要改变形参,可以引用const:
bool all_uppercase(my::string const& s) {
/* check to see whether any character is uppercase */
}
但是,如果形参的目的是向实参中写入内容,则通过非const引用传递
bool try_parse(T text, my::string &out) {
/* try to parse, write result into out */
}
作为一个规则,通过const引用传递更好。 但是如果你需要在本地修改你的函数参数,你最好使用按值传递。 对于一些基本类型,通过值传递和通过引用传递的性能通常是相同的。实际上,内部引用是由指针表示的,这就是为什么你可以期望,例如,对于指针来说,两个传递在性能方面是相同的,甚至通过值传递可以更快,因为不必要的解引用。
通过引用传递比通过值传递更好。我在Leetcode上解lcs问题。它显示了TLE的传递值,但接受代码的传递引用。我花了30分钟才弄明白。
这是我在设计非模板函数的接口时通常采用的方法:
Pass by value if the function does not want to modify the parameter and the value is cheap to copy (int, double, float, char, bool, etc... Notice that std::string, std::vector, and the rest of the containers in the standard library are NOT) Pass by const pointer if the value is expensive to copy and the function does not want to modify the value pointed to and NULL is a value that the function handles. Pass by non-const pointer if the value is expensive to copy and the function wants to modify the value pointed to and NULL is a value that the function handles. Pass by const reference when the value is expensive to copy and the function does not want to modify the value referred to and NULL would not be a valid value if a pointer was used instead. Pass by non-const reference when the value is expensive to copy and the function wants to modify the value referred to and NULL would not be a valid value if a pointer was used instead.
为小类型传递值。
但是,在c++ 11中,如果您要使用数据,则通过值传递,因为您可以利用move语义。例如:
class Person {
public:
Person(std::string name) : name_(std::move(name)) {}
private:
std::string name_;
};
现在调用代码会做:
Person p(std::string("Albert"));
并且只会创建一个对象,并直接移动到类Person中的成员name_中。如果传递const引用,则必须创建一个副本以将其放入name_中。