Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [SOLVED] Reference to String or Texture in map  (Read 2825 times)

0 Members and 1 Guest are viewing this topic.

Oldie

  • Newbie
  • *
  • Posts: 34
    • View Profile
[SOLVED] Reference to String or Texture in map
« on: September 14, 2013, 06:39:05 pm »
Hi,

I have a couple of questions about references to sf::String and sf::Texture contained in std::map.

Firstly, about sf::String.
In my current code, I have:
  • One std::map<std::string, sf::String>, let's call it myMap.
  • One sf::String& referring to one mapped_type of myMap, let's call it myRef.

myRef is initialized from the map:
myRef(myMap.at(oneString));

Through a certain event, I want to make a entire update of myMap, ie. to modify all the mapped_type values (sf::String) in myMap while keeping all the key_type values (std::string). At the same time I want to keep myRef valid, ie. referring to the new mapped_type value. The idea behind having myRef a reference is that I want its value to be automatically updated when I modify the value in myMap.

My initial guess was:
myMap.at(key_value) = new_mapped_value;

So far this has lead to no error in runtime, myRef uses the new string.

But I have checked some stuff inside both SL and SFML documentations.
I understand that a sf::String has a member std::basic_string<Uint32>, ie. std::basic_string<unsigned int>. For the function std::basic_string::operator=, it is said that "Any iterators, pointers and references related to this object may be invalidated."
Should I understand that it depends on the compiler used and/or on the respective sizes of the current and new strings ? Would I have been lucky in runtime so far?

Instead of assigning a new value, I also thought of this:
myMap.erase(key_value);
myMap.insert(std::pair<std::string, sf::String>(key_value, new_mapped_value)); // GCC 4.7

Of course the program either crashes or goes crazy (Valgrind).

For the function std::map::erase, it is said that "Iterators, pointers and references referring to elements removed by the function are invalidated. All other iterators, pointers and references keep their validity."
So myRef becomes invalid indeed.

So what about having one sf::String* instead of sf::String&? Actually the above still holds, right? Reference or pointer, same outcome?

So what about having one std::map<std::string, sf::String*> instead, along with the sf::String&? Should I be assured that myRef cannot become invalid this time, because the assignment concerns a pointer, which is itself of constant size?

Secondly, about sf::Texture.
Here I have:
  • One std::map<std::string, sf::Texture>: myMap2.
  • One sf::Sprite, constructed through a reference to one mapped_type of myMap: mySprite.

mySprite is constructed from a reference, returned by an asset manager:
mySprite(assetManager.getTexture(filename))

I want to make the same kind of update for myMap2 as for myMap. So I used:
myMap2.at(key_value) = new_mapped_value;

So far this has lead to no error in runtime as well: mySprite is still valid and uses the new texture.

I understand that a sf::Texture has several members, which are all of constant size (sf::Vector2u, unsigned int, bool, Uint64). I also understand that the pixels of the texture are stored in the GFX memory, so that those members are light holders in RAM. So, should I understand that the total size of a sf::Texture is constant, and therefore that the function sf::Texture::operator= keeps any iterators, pointers and references, and therefore mySprite, valid?

Thank you if you can confirm/infirm my understanding of things, and also help me find out the best way to proceed here.
« Last Edit: September 15, 2013, 12:58:42 pm by Oldie »
Working on a Tic-tac-toe game

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Reference to String or Texture in map
« Reply #1 on: September 14, 2013, 08:28:46 pm »
Your current code is perfectly ok, the reference that you keep is still valid because the instance is still at the same memory location (operator= changes the contents of the instance, but the instance itself remains the same).

In my opinion, the message from the SL documentation refers to the string as a container, i.e. "if you have an iterator, pointer or reference to one of the string's characters, it may be invalidated".
Laurent Gomila - SFML developer

Oldie

  • Newbie
  • *
  • Posts: 34
    • View Profile
Re: Reference to String or Texture in map
« Reply #2 on: September 15, 2013, 02:13:07 am »
In my opinion, the message from the SL documentation refers to the string as a container, i.e. "if you have an iterator, pointer or reference to one of the string's characters, it may be invalidated".
You have to be right, I mixed things up while trying to apply symmetry between both cases (String and Texture).

Still, what happens if the block of memory right after the old std::string instance is not free to use, and the new std::string is larger than the old one? No space to hold all the characters means reallocation of that std::string instance and therefore invalidity of the reference, right? By the way, the question is independent of the instance being part of a std::map or not.
(An alternative is that there is space in memory right after the old std::string, but not enough for the new one.)

As for sf::Texture, is there no problem anyway, since its size cannot vary, even if the size of the image on disk does change, as explained in my previous message?
(The use case involves a call to sf::Texture::loadFromFile.)

I feel like I am overlooking something here...
Working on a Tic-tac-toe game

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Reference to String or Texture in map
« Reply #3 on: September 15, 2013, 09:16:47 am »
Quote
Still, what happens if the block of memory right after the old std::string instance is not free to use, and the new std::string is larger than the old one?
You have a reference to the string instance, not to its char array. You don't care if the array is moved in memory.

Quote
As for sf::Texture, is there no problem anyway, since its size cannot vary
I think you're mixing things. The size of a class instance can never vary, sizeof(x) is a compile-time constant. The only thing that may change is the size of whatever dynamic memory it internally manages, but this is not your problem. For the instance it's just the value of a pointer that changes.
Laurent Gomila - SFML developer

Oldie

  • Newbie
  • *
  • Posts: 34
    • View Profile
Re: Reference to String or Texture in map
« Reply #4 on: September 15, 2013, 12:57:40 pm »
Alright, that explains why my code has worked so far. Also your explanation is clear, and things are made simple, which is great!

Merci Laurent !

- TOPIC SOLVED -
Working on a Tic-tac-toe game

 

anything