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.