59

What's the best way to delete an std::string from memory allocated on the heap when I'm done using it? Thanks!

bbosak
  • 5,353
  • 7
  • 42
  • 60
  • The same way as for any other object. Really, could you clarify your question? What are you doing, what are you trying to achieve, what did you try and how it didn't work? – Sergei Tachenov Feb 12 '11 at 18:08
  • Can you expand your question? On what context? – vz0 Feb 12 '11 at 18:09
  • Why the downvote? Seems like a perfectly reasonable question that somebody new to C++ would ask. IMO the world needs more programmers who want to know how to clean up after themselves =) – Ryan Mitchell Feb 12 '11 at 18:11
  • 1
    @Ryan Mitchell: 1) this question can be easily answered by reading the first two chapters of most C++ books, and 2) there are thousands of exact duplicates, 3) poorly phrased, it is unclear what the OP wants to ask. – Lie Ryan Feb 12 '11 at 18:15
  • @Ryan, I think it is because of the lack of explanation. I haven't downvoted, but I don't feel like upvoting either. – Sergei Tachenov Feb 12 '11 at 18:16
  • @Sergey the question seems to be from a C guy getting into C++ – Foo Bah Feb 12 '11 at 18:21
  • 3
    First of all - Yes, I am fairly new to C++, and no I am not using a C++ book. I am learning C++ by referencing the MSDN library, and was unable to find anything specific to freeing strings allocated on the heap, and I was unsure if it was a good idea to use the DELETE function, or if I should have used free(&str) or some other function. I can see why it may have received downvotes, but I had tried Google and MSDN before, and was unable to find a good answer, so I decided to post here, and I got the answer I was looking for. – bbosak Feb 12 '11 at 18:23
  • 2
    @IDWMaster: C++ is not a language that you learn from reading the reference documentation here and there, I strongly recommend you to get a C++ book and study it. – Matteo Italia Feb 12 '11 at 18:26
  • I did previously work in C and C#, and it seems to be fairly similar to those languages, although I am now planning on purchasing a book on the language. – bbosak Feb 12 '11 at 18:28
  • @IDWMaster, it's not DELETE, it's `delete`. C++ is a case-sensitive language. And it's not a function, it's an operator. And no, you can't use free(). `delete` is the only correct way to free something created with `new`. You probably couldn't find anything because there is no std::string specifics at all. – Sergei Tachenov Feb 12 '11 at 18:29
  • Sorry, I'd correct it if it would let me edit it... – bbosak Feb 12 '11 at 18:29
  • 1
    @IDWMaster: C++ is similar to C and C# in the syntax, but not in the idioms. – Matteo Italia Feb 12 '11 at 18:33
  • @Matteo As I'm quickly learning. – bbosak Feb 12 '11 at 19:11
  • 3
    @IDWMaster: [Get a book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). You'd laugh if I said "I can fly this plane, I know how to drive a car after all! They both have wheels." Your knowledge of C# or C to C++ is about as applicable. You don't learn a language by pretending they have a 1-1 mapping of functionality, they're different for a reason. Act like you don't know anything and learn that way. As a beginner, you're the last person be have the authority to assert you know what you're doing; you don't. Take our advice. – GManNickG Feb 12 '11 at 21:01

8 Answers8

89

std::string is just a normal class1, so the usual rules apply.

If you allocate std::string objects on the stack, as globals, as class members, ... you don't need to do anything special, when they go out of scope their destructor is called, and it takes care of freeing the memory used for the string automatically.

int MyUselessFunction()
{
    std::string mystring="Just a string.";
    // ...
    return 42;
    // no need to do anything, mystring goes out of scope and everything is cleaned up automatically
}

The only case where you have to do something is when you allocate an std::string on the heap using the new operator; in that case, as with any object allocated with new, you have to call delete to free it.

int MyUselessFunction()
{
    // for some reason you feel the need to allocate that string on the heap
    std::string * mystring= new std::string("Just a string.");
    // ...
    // deallocate it - notice that in the real world you'd use a smart pointer
    delete mystring;
    return 42;
}

As implied in the example, in general it's pointless to allocate a std::string on the heap, and, when you need that, still you should encapsulate such pointer in a smart pointer to avoid even risking memory leaks (in case of exceptions, multiple return paths, ...).


  1. Actually std::string is defined as

    namespace std
    {
        typedef std::basic_string<char> string;
    };
    

    so it's a synonym for the instantiation of the basic_string template class for characters of type char (this doesn't change anything in the answer, but on SO you must be pedantic even on newbie questions).

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • and here I was thinking std::string was a typedef for the template class std::basic_string with a char element type, rather than being a normal class. Not that being a typedef for a template class (or being a struct or being a primitive type) makes any difference to destruction and deallocation of auto and dynamic objects. – Pete Kirkham Feb 12 '11 at 18:19
  • @Matteo, it's still wrong. It's not a specialization, it's an instantiation. And it's especially important to be pedantic on newbie questions because otherwise newbies would easily pick up wrong terms. I couldn't care less about whether it's a specialization or instantiation, but a newbie might think "specialization == typedef" which looks reasonable, but is plain wrong. – Sergei Tachenov Feb 12 '11 at 18:45
  • 1
    @Sergey Tachenov: `std::basic_string` is a specialization, the `typedef` makes a synonym for it; since he said he knows C I supposed that the role of the `typedef` would have been obvious; still, fixed again, next time feel free to perform the edit yourself. – Matteo Italia Feb 12 '11 at 19:40
  • @Matteo, looks like I am a kind of newbie here too. I always though that "specialization" refers to only explicit specializations using `template<>` syntax or to partial explicit specializations. Turns out this is not the case, sorry for misleading comment. – Sergei Tachenov Feb 13 '11 at 09:16
  • @Sergey: strictly speaking it's template instantiation, but I've seen both terms used for it (in that case, *explicit instantiation* is used for what you are saying). – Matteo Italia Feb 13 '11 at 10:44
  • @Matteo, before posting the previous comment, I've found [this definition](http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/index.jsp?topic=%2Fcom.ibm.vacpp7a.doc%2Flanguage%2Fref%2Fclrc16template_specialization.htm): "The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization." Sounds reasonable to me. – Sergei Tachenov Feb 13 '11 at 12:30
  • What if I define string in global scope `string aaa`, then at some point I have set it to something `aaa = string("long string, like a file content......")`. What will happen if I do the assignment AGAIN ?? (so again `aaa = string("another long string"`)? Will the first string be DEACLOCATED from the heap automatically??? – Mike Keskinov May 02 '22 at 17:48
  • 1
    @MikeKeskinov: yes; both assignments create a temporary string, which is move-assigned to `aaa`; the previous content of `aaa` is deallocated automatically on assignment, the (now empty) temporary is destroyed at the end of the expression. Notice that assignments that do not deal with temporaries behave a bit differently (the storage of the target string is recycled for the new content instead of deallocated, so it will keep the existing capacity even if bigger than necessary), but you don't ever risk any memory leak: when the `std::string` is destroyed, its memory is released. – Matteo Italia May 03 '22 at 11:24
12
std::string foo("since it's on the stack, it will auto delete out of scope");

or:

std::string* foo = new std::string("allocated on the heap needs explicit destruction")
delete foo;
PrettyPrincessKitty FS
  • 6,117
  • 5
  • 36
  • 51
4

Use delete if it's on the heap, and nothing at all if it's on the stack.

Zitrax
  • 19,036
  • 20
  • 88
  • 110
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
1

just treat std::string as any basic type.

std::string *str = new std::string("whatever");
///code
delete str;
yu quan
  • 161
  • 1
  • 1
  • 14
1
void foo() {
    string* myString = new string("heap-allocated objects are deleted on 'delete myString;'");
    cout << *myString << endl;
    delete myString;
}

or better yet, avoid pointers when possible and use automatic variables:

void foo() {
    string myString("stack-allocated string is automatically deleted when myString goes out of scope");
    cout << myString << endl;
}
Lie Ryan
  • 62,238
  • 13
  • 100
  • 144
1

If you want to clear out internal std::string's allocation, you'll need to have the following:

std::string str;

// fill str with 250 chars

str.clear(); // clears the content: size = 0, capacity = 250
str.shrink_to_fit(); // shrinks the capacity: size = 0, capacity = 16 or 22 (depends on implementation) 
NutCracker
  • 11,485
  • 4
  • 44
  • 68
0

Maybe your dealing with really freeing the internal string buffer?

For performance reason, most implementation keep the internal buffer allocated, even is the string is "emptied". Additionally: small strings (smaller than sizeof(ptr)) are directly stored in the area that hold pointers. Theses bytes can never be reclaimed during the life of the string.

To free the internals: the classical trick is to use swap within a scope. This force buffer to be really freed (Works also with vector/map/ostream/stringstream etc ...):

string s;                                               // size==0 and capacity==15 as the default proxy of the container (help perf on small string)
s = "Looooooooooooooooooooooooooooooong String";        // size==41 and capacity==47 bytes allocated
s.clear();                                              // size==0  BUT capacity==47 bytes STILL allocated!!
        
s = "Looooooooooooooooooooooooooooooong String";        // size==41 and capacity reuse 47 bytes still allocated. 
s.resize(0);                                            // size==0  BUT capacity==47 bytes STILL allocated!!
// swap with scope to force freeing string internals
{ 
    string o;
    o.swap(s);
}                                                       // size==0 AND capacity==15 (back to smallest footprint possible)
s = "12345";                                            // size==5 AND capacity==15 (the string is IN the container, no new alloc)
BobMorane
  • 3,870
  • 3
  • 20
  • 42
Gordon88
  • 64
  • 3
-1

You can treat std::string like any other class. Use new for allocation, and delete once you're done with it. With C++11, I do not recommend usage of new and delete in most cases. If you need to allocate the string on heap, use std::shared_ptr to wrap it:

std::shared_ptr<std::string> my_string = std::make_shared<std::string>(std::string("My string"));

As soon as all the copies of my_string go out of scope, the associated memory is going to be deleted automatically.

  • `std::shared_ptr` exists to provide elegant proxy over shared ownership semantics and automated reference counting, not to make heap allocation easier. `std::unique_ptr` is a completely different story, though. It could be wise to mention implications of using both before suggesting either... – Mateusz Grzejek Sep 30 '21 at 19:55