For the std::string:
#include <string>
class Bla
{
public:
Bla() {}
const std::string& GetStr() const
{
return m_Str;
}
private:
std::string m_Str = "Hi";
};
int main() {
Bla bla;
std::string currentString = bla.GetStr(); //1. will allocate new string
const std::string& secondString = bla.GetStr(); //2. will be a const reference to m_Str
if (bla.GetStr() == "abc") {} //3. will be a const reference to m_str, and therefore not another allocated string
}
If you assign the result of GetStr(), which is a const reference, to a normal std::string, like 1., the string will be allocated.
If you assign the result of GetStr(), which is a const reference, to another const reference, like 2., they will be referencing the same object, which is m_Str.
If you compare the result of GetStr(), which is a const reference, to another string or to a string literal, like 3., a string will not be allocated, and the comparison will take place with the referenced object, in this case m_Str with the other string, in this case a const char[] (aka string literal). (The one being compared to here is "abc").
m_Str will be allocated, however.
For the std::vector:
If the result of the function returning the std::vector& is assigned to a normal std::vector (not a reference), it is allocated.
If the result of the function returning the std::vector& is assigned to another reference to a vector, then it will not be allocated.
If the result of the function returning the std::vector& is compared to another std::vector or std::vector& using a comparison operator, it is not allocated.
Edit: As Evg pointed out, the operator == has an overload that takes a std::string and a const char*. If it did not exist, bla.GetStr() == "abc" would have had to construct and allocate a new string from "abc" to be able to compare the two.