• Advertisement
Sign in to follow this  

Getting address of an item in a std::vector

This topic is 647 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi Guys,

 

I am wondering how I can (or if it is possible to) get the address of an item that is stored in a vector to reference it directly.

 

I have come up with this so far (which is wrong)

 

 

Asset asset_address(int id)
{
 for (std::vector<Asset>::iterator it = vectorAsset.begin(); it != vectorAsset.end(); ++it)
 {
  if (it->get_id() == id)
  {
   return *it;
  }
 }
 return;  // wont compile because of return type
}

 

 

Any help would be hugely appreciated

 

Thanks in advance :)

Share this post


Link to post
Share on other sites
Advertisement
Asset* asset_address(int id)
{
   auto it = std::find_if(vectorAsset.begin(), vectorAsset.end(), [=] (const Asset& asset) { return asset.get_id() == id; });
   if (it != vectorAsset.end())
      return &(*it);
   else
      return nullptr;
}

Share this post


Link to post
Share on other sites

Thanks man!

 

I understand this is a hazardous thing to do if elements are deleted, sorted, etc. So, I'll use with caution :)

Share this post


Link to post
Share on other sites
Since you are working with a vector the potential issues are not just related to sorting or deleting. Whenever the container invalidates its iterators all pointers you have become invalid as well. See the documentation under "Iterator invalidation".

Additionally, when you swap with another vector your pointers will point to assets in the other vector. Edited by BitMaster

Share this post


Link to post
Share on other sites

Hmm, that's odd.

 

Because the iterator immediately goes out of scope when it returns the address, yet the pointer still seems valid and I am getting the correct data from it after this.

Share this post


Link to post
Share on other sites
Iterators going out of scope and iterators being invalidated are completely different concepts.

Edit: Iterators become invalid (regardless of whether or not an instance of said iterator currently exists) when a container needs to do modifications which change the layout in memory for some or all elements.

In case of a vector, anything that forces a reallocation of the vector will invalidate all iterators (for example a push_back when the vector has no more capacity remaining). It can also invalidate some iterators, for example an erase will invalidate iterators to the removed element and all behind it, including the end-iterator. Edited by BitMaster

Share this post


Link to post
Share on other sites

Ahh ok, thanks for clearing up my confusion :)

 

So as long as you operate on the address returned before any other vector operations are done you should be safe then, right?

Edited by DarkRonin

Share this post


Link to post
Share on other sites
This increasingly feels a bit like an XY problem. Maybe it would be a better idea to talk about what you are trying to accomplish instead of trying to ask how to do it with a vector. For example, I'm worried you might not realize how expensive it can be to modify a vector depending on what your usage pattern is and what exactly Asset is.

Share this post


Link to post
Share on other sites

Ahh ok, thanks for clearing up my confusion :)

 

So as long as you operate on the address returned before any other vector operations are done you should be safe then, right?

 

Yes but that is a very bad idea.

 

A better option would be instead of storing Asset in the vector you store Asset* (or std::shared_ptr<Asset>) and return those. Even if the iterators become invalid your pointer will remain valid (unless you delete the element of course - shared_ptr will solve that issue for you).

std::vector<std::shared_ptr<Asset>> vectorAsset;

std::shared_ptr<Asset> asset_address(int id)
{
   for (auto& asset: vectorAsset)
   {
      if (asset->get_id() == id)
      {
         return asset;
      }
   }
   return nullptr;
}
Edited by Nanoha

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement