Reference to a vector element returned by a function in C ++

Can someone verify that the following is a mistake and explain why? I seem to know, but I do not know the details. (My actual problem is with the enumeration vector, not the ints, but I don’t think it matters.) Suppose I have the following code:

std::vector<int> f (void) { std::vector<int> v; v.push_back(5); return v; } void g (void) { const int &myIntRef = f()[0]; std::cout << myIntRef << std::endl; } 

I fix that myIntRef is a dangling reference right away because the return value of f is not stored anywhere on the stack?

Also, is a valid fix or is it still a bug?

  const int myIntCopy = f()[0]; // copy, not a reference 

In other words, is the return result of f () thrown out before the 0th element can be copied?

+7
source share
2 answers

Yes this is true. When you call:

 return v; 

a temporary copy of v and

 const int &myIntRef = f()[0]; 

initializes your link to the first element of this temporary copy. After this line, a temporary copy no longer exists, which means that myIntRef is an invalid reference, the use of which creates undefined behavior.

What you need to do:

 std::vector<int> myVector = f(); const int &myIntRef = myVector[0]; std::cout << myIntRef << std::endl; 

which (thanks to elision copying) uses the assignment operator to initialize the myVector object with v without creating a copy of v . In this case, the lifetime of your link is equal to the lifetime of the myVector object, which makes it a perfectly valid code.


And to your second question:

“Also, is there a valid fix, or is it still a bug?”

  const int myIntCopy = f()[0]; // copy, not a reference 

Yes, this is another possible solution. f()[0] will access the first element of the temporary copy and use its value to initialize the variable myIntCopy . It is guaranteed that the copy v returned by f() exists at least until the whole expression has been executed, see C ++ 03 Standard 12.2 Temporary objects §3:

Temporary objects are destroyed as the last step in evaluating the full expression (1.9), which (lexically) contains the point at which they were created.

+2
source

This is mistake. At the end of the full expression, const int &myIntRef = f()[0]; the temporary vector will be destroyed and the memory will be released. Any subsequent use of myIntRef is undefined behavior.

In some cases, linking a link to a temporary one can extend the life time of the temporary one. This is not one of such cases, the compiler does not know if the link returned by std::vector<int>::operator[] part of a temporary link or an int link with a static storage duration or any other thing, and it will not extend the service life .

+11
source

All Articles