Should accessors return values or constant references?

后端 未结 8 1261
谎友^
谎友^ 2020-12-05 08:17

Suppose I have a class Foo with a std::string member str. What should get_str return?

std::string Foo::ge         


        
相关标签:
8条回答
  • 2020-12-05 08:39

    The short answer is: it depends :-)

    From the performance point of view returning a reference is (usually) better: you save the creation of a new std::string object. (In this case, the creation is costly enough and the size of the object is high enough to justify make this choice at least worth considering - but this is not always the case. With a smaller or built-in type the performance difference may be negligible, or returning by value may even be cheaper).

    From the security point of view returning a copy of the original value may be better, as constness can be cast away by malicious clients. This is especially to be taken into consideration if the method is part of a public API, i.e. you(r team) have no full control over how the returned value is (mis)used.

    0 讨论(0)
  • 2020-12-05 08:41

    One of the goals of having an accessor method is to try, at least to some extent, to abstract your class implementation from its interface.

    Returning by value is better because there are no lifetime issues with the referenced object. Should you decide not to have a std::string member but, say, a std::stringstream or to create a std::string on the fly you don't have to change the interface.

    Returning by const reference isn't the opposite of taking a parameter by const reference, taking a value by const reference doesn't tie your internal data representation to the external interface.

    0 讨论(0)
  • 2020-12-05 08:42

    I believe the second implementation (const reference) is correct as:

    1. the returned object is immutable and therefore upholds the rules of encapsulation.
    2. it's slightly more efficient as there is no copying of str.

    However the first approach will work almost as well.

    0 讨论(0)
  • 2020-12-05 08:44

    AFAIK, the rule is same as the one which is used while deciding whether to take a function parameter by value or const reference. If the sizeof the value being returned is small enough then I tend to use returning a copy else return a const reference.

    0 讨论(0)
  • 2020-12-05 08:46

    It depends on what you want to do with the return value.

    This is better if you just want to make a query and not modify str.

    const std::string& Foo::get_str() const
    {
        return str;
    }
    

    Otherwise, go for this:

    std::string& Foo::get_str()
    {
        return str;
    }
    

    And if you want a copy/clone of str, then use this:

    std::string Foo::get_str() const
    {
        return str;
    }
    
    0 讨论(0)
  • 2020-12-05 08:48

    Returning by value means you do not have to have an internal std::string stored somewhere in the class for which you return.

    In a pure virtual method it is preferable not to assume that the std::string will be there and therefore to return a std::string by value.

    In a concrete class where there is clearly a std::string member and you are just going to return a reference to it, you can, for efficiency, return it by const reference. Even if you have to change it later, you do not need to change functionality that uses the class.

    In a multi-threaded model where the inner string might change between calls, of course, you probably need to return by value (assuming that users of the class will get a "snapshot" view of the string value at the time of the completion of the call).

    Returning by reference is usually more efficient. I do however have a non-mutable reference-counted string class that you can return by value efficiently and I used to use that quite frequently.

    By the way, some would recommend returning a std::string by const value. I do not think it is the best way to do it, as it prevents allowing the user to "swap" it into a local variable.

    0 讨论(0)
提交回复
热议问题