Werner
Werner

Reputation: 2557

Return C++ iterator reference

Example in which it does work as expected

#include <iostream>
#include <vector>

struct MyClass{


  const std::vector<float>::iterator& begin(){
    return myvec.begin();
  }

  const std::vector<float>::iterator& end(){
    return myvec.end();
  }
  std::vector<float> myvec;
};

int main(){

  std::vector<float> mainvec(8,0);

  MyClass myClass;

  myClass.myvec = mainvec;

  for (std::vector<float>::iterator it = myClass.begin();
      it != myClass.end();++it){
    std::cout << *it << " " ;
  }

  std::cout << std::endl;
}

In this code I get the following output:

0 0 0 0 0 0 0 0 

An example which does NOT works as expected:

#include <iostream>
#include <vector>

struct MyClass{


  const std::vector<float>::iterator& begin(){
    return myvec.begin();
  }

  const std::vector<float>::iterator& end(){
    return myvec.end();
  }
  std::vector<float> myvec;
};

int main(){

  std::vector<float> mainvec(8,0);

  MyClass myClass;

  myClass.myvec = mainvec;

  const std::vector<float>::iterator& end_reference = myClass.end();

  for (std::vector<float>::iterator it = myClass.begin();
      it != end_reference;++it){
    std::cout << *it << " " ;
  }

  std::cout << std::endl;
}

In this code I get the following output:

"empty output"

The first code example

It has the problem in which I invoke (erroneously) the vector begin() and end() instead of MyClass methods.

I have the following minimal code to represent my doubt:

#include <iostream>
#include <vector>

struct MyClass{


  const std::vector<float>::iterator& begin(){
    return myvec.begin();
  }

  const std::vector<float>::iterator& end(){
    return myvec.end();
  }
  std::vector<float> myvec;
};

int main(){

  std::vector<float> mainvec(8,0);

  MyClass myClass;

  myClass.myvec = mainvec;

  for (std::vector<float>::iterator it = myClass.myvec.begin();
      it != myClass.myvec.end();++it){
    std::cout << *it << " " ;
  }

  std::cout << std::endl;
}

I get the following warnings on lines 8 and 12:

returning reference to local temporary object [-Wreturn-stack-address] [cpp/gcc] 

but when I compile and run the program, I get:

0 0 0 0 0 0 0 0 

So, it seems that the local reference is not destroyed when it returns the myvec.begin(). When I first wrote the code, I didn't thought it was going to be a problem, as in my head the begin() method from the vector would return a iterator reference to the first vector place, this iterator for me is not being allocated when I do myvec.begin(), but is a reference to this iterator. So, this warning shouldn't appear, as I am not allocating memory. But since I don't know how this mechanism works, I would like to learn it for writing consistent code. It seems that I can ignore this warning, can't I?

Upvotes: 4

Views: 3110

Answers (1)

log0
log0

Reputation: 10917

std::vector::begin returns indeed a temporary object (see http://www.cplusplus.com/reference/vector/vector/begin/)

Your code is valid since you are binding the temporary object to a const reference (would not be legal with a non const reference), and copy it right away in a local variable it.
edit: My mistake. This is indeed also UB to return a const reference from a temporary.

However assigning this reference to another const reference with a longer lifetime would result in undefined behavior as the lifetime of a temporary object is only extended to the lifetime of the const reference it is directly assigned to.

I would recommend taking into account the warning and return an iterator.

I also recommend reading http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

Upvotes: 2

Related Questions