user81993
user81993

Reputation: 6613

Returning a reference of a vector object, good idea?

I have a need for a 3d vector to store some tile objects, rather than putting a vector inside a vector inside a vector I tried this:

inside a struct
...
vector<sortTile3> data;
uint32_t width, length, height;

sortTile3& At(uint32_t x, uint32_t y, uint32_t z) {
    return data[x * width + y * length + z];
}
...

Seems to work fine, also should be faster, i think, because instead of 3 memory fetches it would do 1 memory fetch and 4 calculations or 2 calculations if i can figure out how to do a fused multiply add.

Anyway, I remember reading something on this very site about returning references being bad. I can see why.. a lot of things can go wrong but shouldn't be the case with this one..or?

Upvotes: 1

Views: 92

Answers (2)

Wintermute
Wintermute

Reputation: 44043

This is fine and usual. The problem with returning a reference concerns (mostly) function-local objects. To wit:

struct foo {
  int data;

  // this is fine
  int &ref1() {
    return data;
  }

  // this is NOT fine
  int &ref2() {
    int localdata;
    return localdata;
  }
}

The reason the latter is not fine is that localdata goes out of scope when foo::ref2 is left, and then the returned reference will not refer to a valid object.

Generally, you have to take care to not keep references to objects longer than their lifetime, but there is nothing inherently wrong with returning a reference to a data member from a member function.

You may, for example, have noticed that std::vector's operator[] returns a reference to its members; it is fine for you to do the same thing. You do, however, have to be careful not to store them longer than they remain valid. For example:

std::vector<int> v(10);
int &r = v[0];
v.resize(20);

// r is no longer valid because v may have relocated its storage.

Note also that there are certain things that you can only achieve by returning a reference. If you want, for example, to be able to do

yourstruct.At(0, 1, 2).foo = bar;

and have the change stick, returning a copy will not be useful to you.

Upvotes: 1

tmlen
tmlen

Reputation: 9090

There can be a problem if the reference gets stored (and not just used temporarily). The reference will get invalidated when the vector reallocates memory or when items in the vector get moved around (insert), or when the vector gets deleted. If the vector is no longer modified after these references get stored, it will be safe.

See http://en.cppreference.com/w/cpp/container/vector on iterator invalidation.

Upvotes: 1

Related Questions