Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: What does a const reference to the return value of a function mean?

Tags:

c++

c++14

Here's a snippet from my C++ code:

std::queue<std::string> get_file_names(const std::string &indir)
{
    std::queue<std::string> file_names;

    fs::recursive_directory_iterator end;
    for (fs::recursive_directory_iterator it(indir); it != end; it++) {
        const std::string &extn = it->path().extension().string();
        if (extn == ".zip") {
            const std::string &file_name = it->path().string();
            file_names.push(file_name);
        }
    }

    return file_names;
}

Is it a good practice to make every string you won't modify a const reference? I have trouble understanding how can such a reference exist in this context at all. Like the return value of it->path().string() above. How can it be assigned to a reference that can be later used outside of the scope of the function when pushed back to a vector?

I feel like it has to do something with std::move.

like image 749
spinlock Avatar asked Apr 03 '21 15:04

spinlock


People also ask

What does it mean to return a const type from a function?

If you say that a function's return value is const: const int g(); you are promising that the original variable (inside the function frame) will not be modified. And again, because you're returning it by value, it's copied so the original value could never be modified via the return value.

What does const reference do?

- const references allow you to specify that the data referred to won't be changed. A const reference is actually a reference to const. A reference is inherently const, so when we say const reference, it is not a reference that can not be changed, rather it's a reference to const.

What does const mean in function?

The const member functions are the functions which are declared as constant in the program. The object called by these functions cannot be modified. It is recommended to use const keyword so that accidental changes to object are avoided. A const member function can be called by any type of object.

Can a const function return a reference?

Then, no, you can't do that; in a const method you have a const this pointer (in your case it would be a const Foo * ), which means that any reference you can get to its fields1 will be a const reference, since you're accessing them through a " const path".

Why is the return value of a function const in C++?

If you say that a function’s return value is const: you are promising that the original variable (inside the function frame) will not be modified. And again, because you’re returning it by value, it’s copied so the original value could never be modified via the return value.

What does it mean when a function returns a reference?

When function returns a reference it means it returns a implicit pointer. Return by reference is very different from Call by reference. Functions behaves a very important role when variable or pointers are returned as reference.

What kind of variables can a function return?

In the last episodes, we covered the first three topics, const functions and const local variables, then const member variables and today we are covering return types. What kind of variables can a function return? It can return values, references and pointers. And all of these can be const. Let’s have a look at each of them.

What is return const pointers in C++?

Return const pointers Pointers are similar to references in a sense that the pointed object must be alive at least as long as the caller wants to use it. You can return the address of a member variable if you know that the object will not get destroyed as long as the caller wants the returned address.


1 Answers

Your code:

const std::string &file_name = it->path().string();

extends the lifetime of the temporary std::string returned by std::filesystem::path::string(). Since you've marked that as const, it can't be moved into file_names, it must be copied. Assuming you want a move, you would write:

auto&& file_name = // ...
file_names.push(std::move(file_name));

Notice that std::queue has a push() overload for r-value references.

Modern C++ provides a lot of opportunities for compilers to optimize, so avoiding questions/"confusion" about dangling references (the auto&& syntax is "new" in C++11) might be a better approach:

auto file_name = // ...
file_names.push(std::move(file_name));

Writing "natural" code that "looks and behaves like the ints" is often a good approach. In the unlikely situation you find that this is really a performance bottleneck, you can revisit; write your code for clarity first.

like image 125
Ðаn Avatar answered Oct 07 '22 12:10

Ðаn