0

What is the result of following statement?

std::string p;
new (&p) std::string("New word");

Does it create a new heap allocation? or does it just replace the static variable ? How does it differ from the following?

p = std::string("New word");
p = new std::string("New word");

EDIT: Thanks guys. Yeah it seems it's a placement new.

  • 5
    The question will make more sense if you post the definition of `p`. – R Sahu Jun 23 '17 at 21:17
  • 1
    Also see: https://stackoverflow.com/questions/8918791/how-to-properly-free-the-memory-allocated-by-placement-new/8918942#8918942 – Mooing Duck Jun 23 '17 at 21:19
  • Might be a dupe of https://stackoverflow.com/q/13370935/10077, though I'm hesitant to hammer it. – Fred Larson Jun 23 '17 at 21:20
  • 2
    looks like placement new – AndersK Jun 23 '17 at 21:20
  • 1
    The first code is undefined behaviour (if an object has a destructor that does something, you can't placement-new over the top of it without calling the destructor first). The second one won't compile – M.M Jun 23 '17 at 22:05

1 Answers1

2
  • new (&p) std::string("New word"); is using placement new. &p must point at a pre-existing block of memory that is at least sizeof(std::string) bytes in size. The std::string object will be constructed inside that memory, instead of in a newly allocated block of memory. The object must be destroyed by calling its destructor directly when you are done using it, eg:

    char buffer[sizeof(std::string)];
    std::string *p = new (buffer) std::string("New word");
    ...
    p->~std::string();
    
  • p = std::string("New word"); could be doing different things, depending on the context in which it is used:

    • if used in a variable declaration statement, p is allocated on stack (automatic) or heap (dynamic) memory (depending on context) and is copy-constructed using the std::string value:

      some_type p = std::string("New word");
      //
      // same as:
      // some_type p(std::string("New word"));
      //
      // if some_type=std::string, same as:
      // std::string p("New word");
      ...
      
    • if used in an assignment statement on a pre-existing object, it is allocating a block of temporary stack (automatic) memory, constructing a new temporary std::string object in that memory, assigning that temp object to p, and then destroying the temp object and freeing the temp memory.

  • p = new std::string("New word"); is allocating a new block of heap (dynamic) memory, constructing the std::string object in that memory, and then assigning the memory address to the p pointer. The object must be destroyed manually using delete:

    std::string *p = new std::string("New word");
    ...
    delete p;
    

In all three cases, the std::string object contains an internal pointer to its character data, which may point to memory on the stack (automatic) or heap (dynamic), depending on where the std::string is allocated, what optimizations it employs, etc.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • What about `p = std::string("New word");` that isn't initializing a new variable? – Barmar Jun 23 '17 at 22:01
  • The only way that can compile is if `p` is an actual `std::string` object (or an object with a `operator=` that accepts `std::string` as input), not a `std::string*` pointer to an object. – Remy Lebeau Jun 23 '17 at 22:02
  • That's what I'm asking about, e.g. `std::string p; ...; p = std::string("New word");`. Does this make a temporary string and copy it, or does copy elision bypass that? – Barmar Jun 23 '17 at 22:04
  • In your first example it may fail due to the char buffer not being aligned for std::string (this is what `std::aligned_storage` is for) – M.M Jun 23 '17 at 22:08
  • @Barmar: `std::string p; ...; p = std::string("New word");` is actually `std::string p; ...; p.operator=(std::string("New word"));` It is constructing a temp object and passing it to `p`, which then copies the data. – Remy Lebeau Jun 23 '17 at 22:15
  • Does copy elision allow it to avoid the temporary? – Barmar Jun 23 '17 at 22:17
  • @Barmar: `p = std::string("New word")` is explicitly constructing a temp `std::string` object, which will then get passed to `std::string::operator=(const std::string&)` (or `std:string::operator=(std::string&&)` in C++11). Copy elision cannot avoid that temp, since it is needed to satisfy the input parameter of `operator=`. If you remove the explicit construction (use `p = "New word"` instead) then the compiler will call `std::string::operator=(const char*)` instead, and avoid making any temps at all. – Remy Lebeau Jun 23 '17 at 22:32