Greg Rynkowski Greg Rynkowski - 1 month ago 15
C++ Question

const auto& for storing functions results, is it worthwhile?

Let assume that we have a function that returns a complex object like

std::string
:

std::string find_path(const std::string& filename);


Is it worthwhile to store the result of calling that method in the
const auto&
?

void do_sth() {
//...
const auto& path = find_path(filename);
//...
}


That kind of approach prevents copying/moving the object. So it is good. But on the other hand,
auto
has been introduced to unify the left side of assignation. Herb Sutter in his presentation from CppCon2014 mentions about C++ left-to-right modern style https://www.youtube.com/watch?v=xnqTKD8uD64 (39:00-45:00).

In C++98 storing the
std::string
at const ref was fine. How is it in C++11?

Update (2016-07-27 2:10 GMT+0):

Sorry, my question was not precise. I meant the coding style - is it better to add
const &
or just stay with
auto
only and let the compiler do whatever it want.

Updated example:

unsigned int getTimout() { /* ... */ }

int getDepth() { /* ... */ }

std::string find_path(const std::string& filename,
unsigned int timeout,
int depth) { /* ... */ }

void open(const std::string& path) { /* ... */ }


Two approaches:

void do_sth() {
//...
auto timeout = getTimeout();
auto depth = getDepth();
const auto& path = find_path(filename, timeout, depth);
open(path)
//...
}


vs

void do_sth() {
//...
auto timeout = getTimeout();
auto depth = getDepth();
auto path = find_path(filename, timeout, depth);
open(path);
//...
}


The question: should we


  • use
    const auto&
    to store complex return objects and
    auto
    for primitives, or

  • use
    auto
    for everything to keep the left-to-right modern C++ style that Herb mentioned in his presentation (link above).


Answer

In C++98 storing the std::string at const ref was fine. How is it in C++11?

Binding a const reference to a temporary string object is fine in C++11. It still has the same behaviour as before.

The theoretical cost of copy-initialization from a temporary (avoiding of which is the advantage of using a const reference) has been greatly reduced in C++11, since moving a string is far cheaper than copying.

The practical cost of copy-initialization has not changed with optimizing compilers, because they may elide the copy/move anyway, so there is no cost - although, whether that is possible, depends on how find_path is implemented.


If you absolutely want to avoid copying/moving the returned string and cannot assume copy elision, then you must create the object outside the function, and pass it to the function by reference. Binding a reference to the return value is not sufficient.

If you want to avoid copying/moving the returned string and can assume copy elision, then using a regular object is just as good as a const reference.

Comments