passing( = returning) by reference a vector at the

2020-05-09 19:24发布

问题:

is this c++ snipet legal?

vector<myType>& aClass::aFunction()
{
    vector<myType> aVec;

    //do stuff

    return aVec;
}

then use it in another function as:

vector<myType> getVec = aFunction();

so basically, I am asking: if I declare getVec and get a reference to aVec vector data, will the data survive the death of aFunction() ?

回答1:

No even if the compiler would let it slip, the variable dies with the scope of the function, so you would have a dangling reference and effectively enter Undefined Behaviour state.

Return by value, any descent compiler will perform (N)RVO. There are some restrictions, so you should alaways check the requirements for your compiler. Especially if there are multiple exit points. But it's best course of action and produces cleanest and fastest code.

Addendum:

It does generate ("just") a warning on both clang++ and g++:

luk32@debianvm:~/projects/tests$ g++ ./dangling_reference.cpp 
./dangling_reference.cpp: In function 'std::vector<int>& test()':
./dangling_reference.cpp:6:17: warning: reference to local variable 'v' returned [-Wreturn-local-addr]
     vector<int> v(10);
                 ^
luk32@debianvm:~/projects/tests$ clang++ ./dangling_reference.cpp 
./dangling_reference.cpp:7:12: warning: reference to stack memory associated with local variable 'v' returned [-Wreturn-stack-address]
    return v;

However I would advise to mark those warnings as errors, as they nearly always are (by nearly I mean to be on the safe side, I don't know how to return reference to a local variable and not enter UB), and consider adding appropriate switches to the compiler commands. E.g.:

g++ -Werror=return-local-addr ./dangling_reference.cpp
clang++ -Werror=return-stack-address ./dangling_reference.cpp

IMO, it's a good practice if your project is big enough for anything more than compiling by hand.



回答2:

No, it's very naughty. You cannot return a reference to a local variable.

Just pass it back by value. The compiler should do return-value optimisation for you, so you shouldn't get wasteful copies.

vector<myType> aClass::aFunction()
{
    vector<myType> aVec;
    // ...
    return aVec;
}


回答3:

No - the automatic object is destroyed when the function returns, leaving the reference invalid. Doing anything with the reference will give undefined behaviour.

Your compiler should warn you about this; if it doesn't, then turn up your warning level.

Return the vector by value instead. If you're worried about the cost of copying it, move semantics and/or elision will take care of that.