96

this is a really simple question but I havn't done c++ properly for years and so I'm a little baffled by this. Also, it's not the easiest thing (for me at least) to look up on the internet, not for trying.

Why doesn't this use the new keyword and how does it work?

Basically, what's going on here?

CPlayer newPlayer = CPlayer(position, attacker);
lysergic-acid
  • 19,570
  • 21
  • 109
  • 218
Henry B
  • 7,947
  • 10
  • 42
  • 46

4 Answers4

80

This expression:

CPlayer(position, attacker)

creates a temporary object of type CPlayer using the above constructor, then:

CPlayer newPlayer =...;

The mentioned temporary object gets copied using the copy constructor to newPlayer. A better way is to write the following to avoid temporaries:

CPlayer newPlayer(position, attacker);
Khaled Alshaya
  • 94,250
  • 39
  • 176
  • 234
  • 7
    Actually compiler will probably optimize it. In that case copy constructor will not get called. http://stackoverflow.com/questions/1758142/why-copy-constructor-is-not-called-in-this-case – BostonLogan Nov 19 '09 at 17:06
  • 7
    An assignment in a declaration isn't any less efficient than using the constructor syntax. If they had been separate statements, than the remark about temporaries would be correct. The essence is that this declares a CPlayer (typically on the stack) rather than allocating space for it from the free store (heap). – Adrian McCarthy Nov 19 '09 at 17:08
  • GCC is not calling the copy constructor, whether or not I have optimizations turned on. – Josh Lee Nov 19 '09 at 17:10
  • They say that in g++, you can disable this optimization with the option -fno-elide-constructors. I have not checked. – BostonLogan Nov 19 '09 at 17:12
  • If this creates an object on the stack can it live past the function it was created in's scope? – Henry B Nov 19 '09 at 17:17
  • 1
    No, almost by definition: Objects on the stack only live while they are in scope. http://stackoverflow.com/search?q=%5Bc%2B%2B%5D+stack+heap – Josh Lee Nov 19 '09 at 17:41
  • 1
    I don't think this answer is precisely correct. The OP's code *looks* like it makes a temporary and then copies it, but the standard 12.1.11 suggests otherwise. It's just a normal constructor call, which jleedev discovered. – Michael Kristofik Nov 19 '09 at 18:01
  • 10
    It's up to the compiler whether to elide copies or not (in the situations where it's permitted). 12.8/15. – Steve Jessop Nov 19 '09 at 18:20
  • 1
    I like the way of `CPlayer newPlayer(position, attacker);` since this style keeps the C++ code style same as C when creating stack variable. Using `CPlayer newPlayer = CPlayer(position, attacker);` is unnecessary and can be confusing. – tonga Sep 16 '13 at 17:54
71

The above constructs a CPlayer object on the stack, hence it doesn't need new. You only need to use new if you are trying to allocate a CPlayer object on the heap. If you're using heap allocation, the code would look like this:

CPlayer *newPlayer = new CPlayer(position, attacker);

Notice that in this case we're using a pointer to a CPlayer object that will need to be cleaned up by a matching call to delete. An object allocated on the stack will be destroyed automatically when it goes out of scope.

Actually it would have been easier and more obvious to write:

CPlayer newPlayer(position, attacker);

A lot of compilers will optimise the version you posted to the above anyway and it's clearer to read.

Timo Geusch
  • 24,095
  • 5
  • 52
  • 70
  • 2
    I don't think this is correct: "An object allocated on the heap will be destroyed automatically when it goes out of scope." – Valentin Jan 18 '13 at 07:42
  • 2
    You're correct, I meant to write "stack", not "heap". Thanks for pointing this out. – Timo Geusch Jan 18 '13 at 16:29
  • Agree on this. We should keep C++ code the same style as C code. So `CPlayer newPlayer(position, attacker);` is better than `CPlayer newPlayer = CPlayer(position, attacker);` if you want to create a stack variable. – tonga Sep 16 '13 at 17:56
12
CPlayer newPlayer = CPlayer(position, attacker);

This line creates a new local object of type CPlayer. Despite its function-like appearance, this simply calls CPlayer's constructor. No temporaries or copying are involved. The object named newPlayer lives as long as the scope it's enclosed in. You don't use the new keyword here because C++ isn't Java.

CPlayer* newPlayer = new CPlayer(position, attacker);

This line constructs a CPlayer object on the heap and defines a pointer named newPlayer to point at it. The object lives until someone deletes it.

Michael Kristofik
  • 34,290
  • 15
  • 75
  • 125
  • 4
    "No temporaries or copying are involved" -- This is not exactly true. There is no such guarantee. But every decent compiler should elide the copy. – sellibitze Nov 19 '09 at 21:45
  • (Re)learning C++ now after over a decade of .NET development. I had a C++ in college about 20 years or so ago but haven't touched it since. Would the reason for making a heap-allocated reference be for like a class-level variable that you might access in various functions or other classes? Is there a point to making a heap-allocated variable instead of a stack-allocated one where it will only be used in a single function? – clamum May 16 '22 at 07:03
  • 1
    @clamum That’s a separate question with lots of answers already on SO. Here’s one good one: https://stackoverflow.com/a/6500497/46821 – Michael Kristofik May 17 '22 at 12:21
7

newPlayer is no dynamically allocated variable but an auto, stack-allocated variable:

CPlayer* newPlayer = new CPlayer(pos, attacker);

is different from

CPlayer newPlayer = CPlayer(pos, attacker);

newPlayer is allocated on the stack via the normal CPlayer(position, attacker) constructor invocation, though somewhat verbose than the usual

CPlayer newPlayer(pos, attacker);

It's basically the same as saying:

int i = int(3);
digitalarbeiter
  • 2,295
  • 14
  • 16
  • 2
    Careful here. It's a "copy initialization". It's *not* an assignment. – sellibitze Nov 19 '09 at 21:41
  • I stand corrected, it's not an assignment; even the copy constructor isn't involved. Edit answer accordingly. – digitalarbeiter Nov 20 '09 at 09:42
  • 2
    Sure, the copy ctor is (at least logically) involved. You'll notice that if you make your copy ctor private. Then, this copy initialization won't work anymore. The C++ standard requires an accessible copy ctor even when the compiler is able to optimize out the copy. – sellibitze Nov 20 '09 at 22:40
  • no, new allocates on the heap, your second player is on the stack thought –  Feb 09 '12 at 09:58