Just a quick question about a function like this:
class Test {
public:
Test(vector<int>& v) {
v_ = v;
}
private:
std::vector<int> v_;
};
What’s the difference between using Test(vector<int>& v) and Test(vector<int> v)? I seem to know that the first one should be faster since it is pass-by-reference. But I’m not so sure whether there are other differences.
The difference is that with
Test(vector<int>& v)(which BTW is an lvalue reference) v refers to the original object, while withTest(vector<int> v)you have a copy. The following example code demonstrates the difference with anintand a normal function (note that forint, pass-by-value is actually faster!):The output of this is:
As you see, with call by value, the argument and the passed variable are completely separate. Incrementing the argument does not change the passed variable, and incrementing the passed variable does not change the argument. On the other hand, with pass by reference, the argument just gives access to the passed variable: It doesn’t matter which one you increment because effectively, they are the same. With pass by const reference, they are also the same, but you are not allowed to mosify the argument (there are ways around this, though). However, the argument still reflects any changes to the passed variable.
Those are the differences in functionality. However there are some more differences: For pass by value and pass by const reference, you can use an rvalue, like
call_by_value(2)orcall_by_const_reference(2). For call by value, it’s obvious what happens: The argument gets the value 2, and that’s it. However for const reference, there’s an object expected (you could for example take the address of that object in the function). Therefore in that case a temporary object is created. For call by non-const reference, you cannot pass an rvalue.C++11 adds another type to the mix, namely rvalue references. Those are denoted with
&&instead of&. Inside the function they behave exactly like normal (lvalue) references, but they differ in that they can be bound to rvalues, even if they are not const. Moreover, if you use them as return type, the call expression will be of rvalue type as if you had returned a value. Especially, you would not be able to pass the result of a function returning an rvalue reference to a function expecting an lvalue reference, just like you couldn’t do that with the literal 2.