-2

I am testing some pointers in c++. My code looks like this:

#include <iostream>
#include <vector>
using namespace std;

vector <int>& vec_return(){
    vector<int> test_vec;
    test_vec.push_back(1);
    test_vec.push_back(2);
    test_vec.push_back(3);
    test_vec.push_back(4);
    test_vec.push_back(5);

    return test_vec;
}

int main(){
    vector <int>& test_vec = vec_return();
    for(int i = 0; i < test_vec.size(); i++){
        cout<<test_vec[i];
    }
    return 0;
}

I am thinking the vec_return() function should return the pointer of a test_vec and then in main it should be printed but instead it doesn't do anything. Any suggestions?

Banned
  • 43
  • 6
  • test_vec is defined in the scope of the function. You are returning a reference to an object that goes immediately out of scope after the return. This gives undefined behavior. – Chiel Aug 10 '17 at 08:14

3 Answers3

1

Returning references to stack variables is undefined behaviour: you create a variable in vec_return, it gets destroyed before exiting from this function, but you still keep a reference to it in main. Change signature of vec_return() to be vector<int> vec_return(), so that compiler can perform copy elision and make sure that the object is constructed only once.

Also, it's better to call test_vec.reserve(N); in vec_return before pushing anything into it to pre-allocate memory, where N is the expected number of calls to push_back, or (since C++11) initialise it directly like this: vector<int> test_vec{1, 2, 3, 4, 5}.

Dev Null
  • 4,731
  • 1
  • 30
  • 46
  • Ok, but then in the main if I write vector& test_vec = vec_return(). It gives the error. and If i ignore the ampersand It will create new vector, and I don't want it. what to do? – Banned Aug 10 '17 at 08:14
  • 1
    The compiler will use [return value optimisation](http://en.cppreference.com/w/cpp/language/copy_elision) and the object will be constructed only once. – Dev Null Aug 10 '17 at 08:16
0

This function returns reference to temporary object

vector <int>& vec_return(){

so using result of this function in the main() is undefined behavior.

ikleschenkov
  • 972
  • 5
  • 11
  • Ok, but then in the main if I write vector& test_vec = vec_return(). It gives the error. and If i ignore the ampersand It will create new vector, and I don't want it. what to do? – Banned Aug 10 '17 at 08:14
  • Pass reference to empty vector into the `void vec_return(vector &) ` and fill it in the function. – ikleschenkov Aug 10 '17 at 08:15
  • 2
    The better option is to return by value. In this case RVO will probably (until C++17) / definitely (since C++17) make the object to be constructed only once. – Dev Null Aug 10 '17 at 08:18
  • @DevNull any *real* compiler that does that? I didn't found any, between Intel , MS and PGI, copy constructors are called, in case of GCC - move one. – Swift - Friday Pie Aug 10 '17 at 08:29
  • @Swift at least gcc >= 4.9.2 and clang >= 3.6.1 do it [*live example*](http://coliru.stacked-crooked.com/a/3977e69edb60078d). – Dev Null Aug 10 '17 at 08:35
0

With power comes responsibility...

Returning a reference to a local variable results in a dangling reference, i.e., a reference to unallocated data, which is UB.

std::vector<int>& vec_return() {
    std::vector<int> test_vec; // Create local object.

    /* ... */

    return test_vec; // Return reference to local object.
} // Here all local objects are destroyed.

Instead, return by value. Any decent compiler will elide (optimize away) the copy. Since C++11, the standard even guarantees a move construction at the call site if no optimizations are available.

std::vector<int> vec_return() {
    return {1, 2, 3, 4, 5};
}

The C++17 standard (finalized but not ISO published) even guarantees the NRVO optimization.

Felix Glas
  • 15,065
  • 7
  • 53
  • 82
  • Ok, but then in the main if I write vector& test_vec = vec_return(). It gives the error. and If i ignore the ampersand It will create new vector, and I don't want it. what to do? – Banned Aug 10 '17 at 08:32
  • @Banned No, you will _not_ create a new `std::vector` when you remove the ampersand. The compiler will optimize it away (even when looking at the code, it may look like a copy is being made)! – Felix Glas Aug 10 '17 at 08:34
  • @Banned Look at [this example](http://coliru.stacked-crooked.com/a/d0384fc4e50b0bea) where a local object is returned by value while optimizations are turned on. – Felix Glas Aug 10 '17 at 08:43