0

Does returning a std::string (and for that matter, std::vector) from a class allocate memory?

If I have this class:

class Bla
{
    public:
        Bla();
       
        const std::string& GetStr() const
        {
            return m_Str;
        }  

    private:
        std::string m_Str;
};

And I have some code like this:

std::string currentString = Bla.GetStr();
if (Bla.GetStr() == "abc"){}

Do both of these allocate an entirely new string?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770

2 Answers2

1

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.

  • So any time I manipulate the return result from `GetStr()` it allocates a new `std::string`, but whenever it is returned that isn't to another `std::string`, it doesn't allocate? –  Apr 13 '21 at 21:10
  • 5
    I think you should post an answer that shows the difference between assigning the return value to a reference, and assigning the return value to a new object. I think the OP is getting confused by your answer. – PaulMcKenzie Apr 13 '21 at 21:12
  • 2
    One thing that is worth mentioning explicitly is the existence of `operator==` that takes `std::string` and `const char*`. Had it not existed, `s == "abc"` would have constructed a new `std::string` from `"abc"` first. – Evg Apr 13 '21 at 21:38
  • @Evg Yes you are absolutely correct I will add that –  Apr 13 '21 at 21:38
  • @PaulMcKenzie I don't have enough reputation to comment on your post, https://stackoverflow.com/questions/21943621/how-to-create-a-contiguous-2d-array-in-c/21944048#21944048 but i suppose I can ask here, is there any benefit to this vs a `std::vector` in terms of performance? Does `std::vector` do this behind the scenes? –  Apr 14 '21 at 00:31
  • @aksjdhjkkjanqbdkjasndkjn Please go to the link and comment on the answer given. – PaulMcKenzie Apr 14 '21 at 04:14
  • @PaulMcKenzie I can't, I need 50 reputation to do that –  Apr 14 '21 at 05:11
0

Once std::string is returned from a function it is called to the move constructor which ensures that the memory of the string is transferred to the outer scope

Ido
  • 168
  • 9