My question revolves around the mechanics of copy-construction and reallocation.
I have a class, that collects strings. After adding a string to the collection, the string is copied and stored in a vector. But as I also need access to the collection of all the string as const char * const*
, I also store the pointers to the data of each string via .c_str()
.
class MyStrings {
private:
std::vector<std::string> names;
std::vector<const char*> cStringPointers;
public:
const char *const *Data() const
{
return this->cStringPointers.data();
}
void Add(const std::string &name)
{
// copy [name] and store the copy in [this->names].
this->names.push_back(name);
// Store the pointer to the data of the copy.
this->cStringPointers.push_back(this->names.back().c_str());
}
}
I am aware, that storing pointers to elements of a vector is bad, because when the vector gets resized, i.e. has to reallocate his memory, those pointers would not be valid anymore.
But I am storing just the pointers to the data. So here is what I think:
If names
gets resized, it will move-construct all the strings it contains and so those strings will not allocate new memory, but instead just use the already allocated memory and so my pointers in cStringPointers
would still be valid.
My question is now simply: Have I missed something that would make this code unsafe or cause undefined behaviour?
(Assuming that I don't use any exotical architexture and or compiler.)
My question is now simply: Have I missed something that would make this code unsafe or cause undefined behaviour?
Yes: you have missed Small String Optimization. It is permitted by the standard and widely implemented, and will lead to dangling pointers as the strings actually move their data to their new location.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With