Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return reference to a vector member variable

I have a vector as member in a class and I want to return a reference to it through a getVector() function, so as to be able to modify it later. Isn’t it better practice the function getVector() to be const? However I got an error “qualifiers dropped in binding reference of type…” in the following code. What should be modified?

class VectorHolder { public: VectorHolder(const std::vector<int>&); std::vector<int>& getVector() const;  private: std::vector<int> myVector;  };  std::vector<int> &VectorHolder::getVector() const { return myVector; } 
like image 909
arjacsoh Avatar asked Dec 05 '11 10:12

arjacsoh


People also ask

How do you return a vector reference?

vector<SalesItem> *getSalesItems(); returns a pointer and does not return a reference. void Invoice::getSalesItems() doesn't return anything. The function definition in the class and the declaration must be the same: vector<SalesItem> & getSalesItems(); returns a vector by refernece.

Can a method return a reference variable?

A C++ function can return a reference in a similar way as it returns a pointer. When returning a reference, be careful that the object being referred to does not go out of scope. So it is not legal to return a reference to local var. But you can always return a reference on a static variable.

Can you store references in a vector?

You can't take the address of a reference, since attempting to do so would result in the address of the object being referred to, and thus you can never get a pointer to a reference. std::vector works with pointers to its elements, so the values being stored need to be able to be pointed to.


2 Answers

Since it is a const member function, the return type cannot be non-const reference. Make it const:

const std::vector<int> &VectorHolder::getVector() const {    return myVector; } 

Now it is okay.

Why is it fine? Because in a const member function, the every member becomes const in such a way that it cannot be modified, which means myVector is a const vector in the function, that is why you have to make the return type const as well, if it returns the reference.

Now you cannot modify the same object. See what you can do and what cannot:

 std::vector<int> & a = x.getVector();       //error - at compile time!   const std::vector<int> & a = x.getVector(); //ok  a.push_back(10);                            //error - at compile time!   std::vector<int>  a = x.getVector();        //ok  a.push_back(10);                            //ok 

By the way, I'm wondering why you need such VectorHolder in the first place.

like image 146
Nawaz Avatar answered Sep 23 '22 03:09

Nawaz


it's not unusual to declare both const and mutable variants, like so:

std::vector<int>& VectorHolder::getVector() {   return myVector; } const std::vector<int>& VectorHolder::getVector() const {   return myVector; } 

the underlying problem with your program is that you return a non-const reference from a const method.

std::vector<int>& VectorHolder::getVector() const {   return myVector; // << error: return mutable reference from const method } 

so you make it const using this form:

const std::vector<int>& VectorHolder::getVector() const {   return myVector; // << ok } 

and when this is in a non const method or the client holds a non-const reference, then you can legally use a non-const method:

std::vector<int>& VectorHolder::getVector() {   return myVector; // << ok } 

finally, you could return a value (in some cases):

std::vector<int> VectorHolder::getVector() const {   return myVector; // << ok } 

because the copy requires no mutation and provides no exposure to the internal data.

so you will end up declaring both variants quite often.

the results of declaring both are:

VectorHolder m; const VectorHolder c;  m.getVector().size(); // << ok c.getVector().size(); // << ok - no mutation  m.getVector().push_back(a); // << ok c.getVector().push_back(a); // << error: attempt to mutate const reference because the const vector is returned 

so it all works out nicely (apart from the redundancy of the methods).

like image 43
justin Avatar answered Sep 23 '22 03:09

justin