I am learning STL these days and I was wondering if STL containers return by reference?
e.g:
vector.first();
map[key];
*vector.begin();
Or any possible return that ends with element (or value type) of container
e.g:
std::vector<int> elements;
elements.push_back(20);
elements[0]=60; // this will also change the value
elements.front() = 23; // even the functions also behave same way like subscript operator
is this the case with all containers? or there are some points to consider which I didn’t show?
Returning the added element, or the container in container member functions is not possible in a safe way. STL containers mostly provide the “strong guarantee”. Returning the manipulated element or the container would make it impossible to provide the strong guarantee (it would only provide the “basic guarantee”). An explanation of these terms is provided at boost’s website on Exception-Safety in Generic Components. See below from Boost’s website.
Back to the topic: Per this previous SO answer, the reason behind this is, that returning something could possibly invoke an copy-constructor, which may throw an exception. But the function already exited, so it fulfilled its main task successfully, but still threw an exception, which is a violation of the strong guarantee. You maybe think: “Well then lets return by reference!”, while this sounds like a good solution, its not perfectly safe either. Consider following example:
Still, if the copy-assignment operator throws, we don’t know if push_back succeeded or not, thus indirectly violating the strong-guarantee. Even though this is not a direct violation. Of course using
MyClass& bar = //...instead would fix this issue, but it would be quite inconvenient, that a container might get into an indeterminate state, just because someone forgot a &.A quite similar reasoning is behind the fact that
std::stack::pop()does not return the popped value. Insteadtop() returns the topmost value in a safe way. after calling top, even when a copy-constructor, or a copy-assignment constructor throws, you still know that the stack is unchanged.