skip to Main Content
const vector<int>& getVec(const vector<int> &vec)
{
    return vec;
}

My function is like this and, if I call getVec with a temporary object, can the code be safe?

int main()
{
   const vector<int> &v = getVec({1,2,3,4,5});
}

I am running this code in g++ and Visual Studio but I get two different results:

  • g++ tells me: the function’s vector is the same as v and they have the same value.

  • Visual Studio tells me: the function’s vector has the same address as v but v.size() is only 0, not 5

Is there a standard answer for this situation? Can a const reference return value only refer to values that existed before the function body?

2

Answers


  1. As already mentioned in the comments, it is undefined behavior. It can be seen from C++11 standard draft, section 12.2/5.

    The second context is when a reference is bound to a temporary.119 The temporary to which the reference is
    bound or the temporary that is the complete object of a subobject to which the reference is bound persists
    for the lifetime of the reference except:

    • A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of
      the full-expression containing the call.
    • The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not
      extended; the temporary is destroyed at the end of the full-expression in the return statement.

    As we can see, Neither function argument reference nor return reference extend the lifetime of temporary {1,2,3,4,5}. So in main() you have undefined behavior, you might end up with dangling reference.

    Login or Signup to reply.
  2. The code as shown is well-formed and doesn’t have any undefined behavior. Only if you actually use v later, then there will be undefined behavior.

    When calling getVec a const vector<int> temporary object will be materialized and initialized with {1,2,3,4,5}, so that the reference in the function parameter can bind to it.

    Temporary objects live (by default) until the end of the full-expression in which they are materialized (which here is the expression getVec({1,2,3,4,5}) together with the initialization of v). Binding them to a reference for the first time may extend the lifetime (under certain additional conditions), but this specifically does not apply to references in function parameters and wouldn’t really help anyway, since the reference in the function parameter itself doesn’t have a longer lifetime.

    So the temporary object lives long enough for v to bind to it, but is then after the initialization of v immediately destroyed.

    Therefore v will be dangling after its initialization and actually using it will cause undefined behavior. But simply initializing it this way will not.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search