-1

When I was having a go with std::string, I decided to do the following:

int main(int argc, char **argv)
{
    std::string s = "Hello World";
    s.~basic_string();
    std::cout << s.c_str();
}

However, it prints nothing, and there is no garbage. However, in my basic_string class, when the destructor is called, I get garbage. How does the std::string handle this? Mine uses an allocator and constructs, destroys, allocates and deallocates, yet it still doesn't work.

Note: I'm not looking for a solution to my class, but to find out how std::string does it.

Joseph
  • 589
  • 1
  • 5
  • 13
  • 13
    You do realize this is illegal, right? – jrok Mar 05 '14 at 18:31
  • 7
    Undefined Behaviour! You just got a lucky day – Sebastian Hoffmann Mar 05 '14 at 18:32
  • 6
    Why would you care what the state of your object is after it's been destroyed? There's nothing to fix. – chris Mar 05 '14 at 18:33
  • 4
    It could be because [Short string optimization](http://stackoverflow.com/questions/10315041/meaning-of-acronym-sso-in-the-context-of-stdstring). Open the header and check for yourself :) – jrok Mar 05 '14 at 18:34
  • 1
    If I'm not mistaken, you should get a double free error because the destructor is called twice. –  Mar 05 '14 at 18:36
  • It's not clear from your question just what it prints. Are the single quotes part of the output? Is the `(NULL)` part of the output? – Keith Thompson Mar 05 '14 at 18:43

3 Answers3

5

First, you shouldn't explicitly call the destructor except in a very few specific cases, this is not one of those. When the string goes out of scope the destructor will be called automatically as guaranteed by the standard.

Second, what were you expecting other than garbage when using a destroyed object? This is undefined behavior which should be avoided. If you want to limit the scope then use curly braces then make a sub scope and cause objects destructors to be called and things to be cleaned up.

int main(int argc, char **argv)
{
    { // new scope
      std::string s = "Hello World";
      std::cout << s;
    } // s destructor called for you

  // other stuff
}
AJG85
  • 15,849
  • 13
  • 42
  • 50
0

It is undefined behavior to invoke a destructor on an object whose lifetime has ended. std::string has a non-trivial destructor, so by the time it goes out of scope, its lifetime has already ended. The destructor that is automatically called should result in a double free error. Because it is undefined behavior, nothing is guaranteed.

Does explicitly calling destructor result in Undefined Behavior here? covers this in great detail.

Community
  • 1
  • 1
-1

Though it is undefined behaviour because the object was destroyed nevertheless I can guess what occurs behind the scene.

When an object of type std::basic_string is empty nevertheless the following construction s[0] is valid. For exampe

std::string s;

std::cout << s[0];

In this case the class returns a reference to an object of type char that was zero initialized. So it seems that the class contains such a data member that has value char( 0 ). So when a memory was not allocated that is when the object is ampty the class returns the pointer to this data member when for example c_str() is called.

So it seems that the destructor after freeing early allocated memory sets the corresponding pointer to NULL. When you call function c_str() then it checks whether the pointer is equal to NULL. If so then it returns pointer to the data member that I have described.

It could be the solution you are looking for.:)

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335