7

Constantness

class MyClass {
// ...
private:
    std::string m_parameter;
// ...
}

Pass-by-value:

void MyClass::SetParameter(std::string parameter)
{
    m_parameter = parameter;
}

Pass-by-ref:

void MyClass::SetParameter(std::string& parameter)
{
    m_parameter = parameter;
}

Pass-by-const-ref:

void MyClass::SetParameter(const std::string& parameter)
{
    m_parameter = parameter;
}

Pass-by-const-value:

void MyClass::SetParameter(const std::string parameter)
{
    m_parameter = parameter;
}

Pass-by-universal-ref:

void MyClass::SetParameter(std::string&& parameter)
{
    m_parameter = parameter;
}

Pass-by-const-universal-ref:

void MyClass::SetParameter(const std::string&& parameter)
{
    m_parameter = parameter;
}   

Which variant is the best (possibly in terms of C++11 and its move semantics)?

PS. May be bodies of the functions is in some cases incorrect.

vladon
  • 8,158
  • 2
  • 47
  • 91
  • 3
    Your last two examples are not universal references, they are rvalue references. – TartanLlama Jul 14 '15 at 09:31
  • Related/duplicate: http://stackoverflow.com/q/31154012/ http://stackoverflow.com/q/21035417/ and many more – dyp Jul 14 '15 at 09:37
  • The answer may differ according to what are the semantics of the class and what you are trying to achieve. If unsure/general case const ref is the best – Andre Jul 14 '15 at 09:44
  • @Andre What I am trying to achieve: it is a simple setter for private member. No matter what semantics is. – vladon Jul 14 '15 at 09:52

2 Answers2

8
  1. Pass by value: not good in general as a value copy might be taken. (Although a move constructor might mitigate).

  2. Pass by reference: not good as the function might modify the parameter passed. Also an anonymous temporary cannot bind to a reference.

  3. Pass by const reference: still the best. No copy taken, function cannot modify the parameter, and an anonymous temporary can bind to a const reference.

  4. Passing by && variants: Currently pointless, as there are no move semantics given the way you've written the function bodies. If you'd written std::move(m_parameter, parameter) in place of the assignment then this might win over (3) in some cases, and the compiler will pick the better.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 3. When passing by const reference, there IS copy of value from where ref is pointed to. And calling `SetParameter("blahblahblah")` makes temporary, which is copied then. – vladon Jul 14 '15 at 09:39
  • I disagree that pass by value is not good in this case. There's going to be a copy anyway, so making it in the interface then calling `std::move` on it may be more efficient than the const reference version. – TartanLlama Jul 14 '15 at 09:40
  • 2
    @TartanLlama Both pass-by-value and pass-by-const-ref have cases where they're (theoretically) more efficient than the other one. – dyp Jul 14 '15 at 09:44
  • @dyp yeah, that's why I said "may be". I was just disagreeing that pass-by-value is not good rather than arguing that it's the best option :) – TartanLlama Jul 14 '15 at 09:45
1

See 'Effective C++' Scott Meyers - If the private member is a built in type then it can be more efficient to pass by value than pass by reference (which are typically implemented as pointers in the compiler). This is also true for iterators and function objects in STL which are designed to be passed by value. Otherwise pass by reference-to-const is preferable.

Ed James
  • 21
  • 2