1

Does new in C++ call a constructor behind the scenes? Or is it the other way around?

I have seen code like new MyClass(*this) which confuses me, since I didn't know that new could take arguments.

Maybe that's because new can call a constructor and, as a result, it can take the arguments declared by a constructor?

Josh
  • 11,979
  • 17
  • 60
  • 96
  • 1
    @appleapple That is **not** placement new – NathanOliver Jan 04 '23 at 15:53
  • 8
    While this isn't a bad question, it's a sign you need a [good C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). A constructor can take all kinds of arguments. Why would you think otherwise? How else does `std::string` get constructed with a pre-existing value? – tadman Jan 04 '23 at 15:53
  • @NathanOliver oh right. it's just a constructor argument – apple apple Jan 04 '23 at 15:53
  • 5
    `new MyClass(*this)` calls the constructor, you are passing the arguments to the constructor, not `new` itself. – Quimby Jan 04 '23 at 15:54
  • 3
    Look at [cppreference](https://en.cppreference.com/w/cpp/language/new) (2) – Jarod42 Jan 04 '23 at 15:54
  • The expression `new MyClass(*this)` does result in a constructor call, assuming the memory for the object was successful. This is not different to the expression `new MyClass`; the latter just uses a constructor that works without specifying any constructor arguments... – fabian Jan 04 '23 at 16:17

3 Answers3

4

MyClass(*this) creates an object of type MyClass by calling its constructor and passing *this as an argument. Putting new behind it means the object is allocated on the heap instead of the stack. It's not new which is taking the argument, it's MyClass.

David G
  • 94,763
  • 41
  • 167
  • 253
3

There is a difference between new and operator new. The new operator uses a hidden operator new function to allocate memory and then it also "value-initializes" the object by calling its constructor with the parameters after the class name.

In your case you call new which allocates memory using ::operator new() and then it initializes an object of MyClass class in that memory using a constructor with the parameter *this.

#include <iostream>

class A {
    public:
        int m_value; 
        A(int value): m_value(value){};
};

int main (){

    int *a  = new int; 

    auto b= new A(1); 

    std::cout << *a << std::endl; 
    std::cout << b->m_value << std::endl; 
    printf("%02x ", *b);

}

Program returned: 
0
15
0f

As you can see, the new for the a variable creates only a pointer that is value-initialized to 0. That's why when we dereference it we have 0 (all bit all 0, int is 4 bytes most of the time and the pointer point to a memory content = to 0x0000)

But for the b variable we pass parameters. And if we look at the memory content of the b object we can read 0f which means it contains 15 (the member value)

jdenozi
  • 212
  • 1
  • 11
  • 2
    I suspect the OPs confusion comes from awareness that `operator new` can be overridden. It might be worth noting that the `new` operator calls `operator new` and then it calls the constructor on that memory. – Mooing Duck Jan 04 '23 at 16:23
  • Thanks! @MooingDuck I just updated the code snippet with what I understood you meant. Please let me know if you think that's wrong! – Josh Jan 04 '23 at 21:30
  • 1
    @Josh: I have reworded the answer to hopefully answer the question without diving *too much* into arcane details of what value-initialization is, or how overriding `operator new` works. Neofelis: I dislike that I made so many changes to your post, but apparently Josh was still confused. I hope the edits are ok. – Mooing Duck Jan 05 '23 at 16:48
  • For those curious, this offers a little more insight into overriding `operator new`: http://coliru.stacked-crooked.com/a/897bc134e2cc56f0 It's interesting, but usually pointless, and best to avoid this arcane corner of C++. – Mooing Duck Jan 05 '23 at 16:48
  • For those curious, this answer offers a little more insight into how to provide parameters to `operator new` itself: https://stackoverflow.com/questions/34800940/parameters-to-operator-new. tldr the extra parameters go between `new` and the class name. `A* p = new("new-parameter") A("A-ctor-parameter");` – Mooing Duck Jan 05 '23 at 16:51
  • "int is 4 bits most of the time" << no, it's 4 or 8 _bytes_, i.e. 32 or 64 bits most of the time. also, `0x0000` would be 2 bytes / 16 bits (one nibble is 4 bits or half a byte long and you put four nibbles here) – CherryDT Jan 05 '23 at 16:56
  • No worries, your changes were useful. And you managed to keep the answer "simplify" to avoid getting lost in the details. By the way, Josh seemed to have understood because no new good news – jdenozi Jan 05 '23 at 16:57
  • CherryDT, Sorry, the word bytes in my language does not exist and I got everything mixed up. – jdenozi Jan 05 '23 at 17:03
0

This is not new taking arguments, it's the constructor taking arguments.

Alex Bochkarev
  • 2,851
  • 1
  • 18
  • 32
  • 2
    You may need to add a tutorial on the difference between a new-expression and the new operator. – Spencer Jan 04 '23 at 15:56