3

This question may be a duplicate. I have been looking online everywhere to figure this out, but I can't find anything. What is the difference between 'new' and '*new'?:

int main()
{
    class Cat
    {
        //Code
    }

    new Cat();
    *new Cat();

    return 0;
}
0x90
  • 39,472
  • 36
  • 165
  • 245
  • 1
    I'm curious, where did you see this? – JBentley Apr 20 '13 at 15:36
  • @AlokSave no its not a duplicate of that. im still learning c++ and i dont even know what a memory leak is –  Apr 21 '13 at 01:04
  • @JBentley Im from java. I just want to be able to put new objects in an array/list. In java you do "object[5] = new object();" –  Apr 21 '13 at 01:07
  • @Harry I meant did you see an example of `*new` in some code you saw somewhere? – JBentley Apr 21 '13 at 01:39
  • @JBentley nope. I mean I havent seen this in c++ i have only seen it in java. im trying to figure out how to make a new object and store it in the memory like you do in java. –  Apr 21 '13 at 01:53
  • @harry I see. Well you should look into the [difference between stack and heap memory](http://stackoverflow.com/questions/408670/stack-static-and-heap-in-c) and the [performance considerations](http://stackoverflow.com/questions/161053/c-which-is-faster-stack-allocation-or-heap-allocation) of each. You shouldn't just place all your objects on the heap (which is what `new` does) by default. Also, even when you do want heap memory, avoid `new` and use smart pointers instead, as they take care of the memory management for you. – JBentley Apr 21 '13 at 02:15

3 Answers3

17

These are not two separate things. There's not a new and a *new. The second is simply applying unary * to the result of new Cat().

new Cat() is a new-expression. It dynamically allocates and initialises a Cat object and evaluates to a pointer to that object. If you then apply unary * to that pointer, you dereference it to get the Cat object.

There is not very often a good reason to apply unary * immediately to a new-expression. The reason is because you're immediately following the pointer and haven't stored the pointer anywhere. Consider if you had done this:

Cat c = *new Cat();

This would result in a memory leak that you can't recover from. A Cat object is dynamically allocated and then copied into c. The dynamically allocated Cat now lingers around and you don't have a pointer to it through which you can delete the object. This is very bad.

Cat& c = *new Cat();

This is a little better, because at least now c is just a reference to the dynamically allocated object. You can always do delete &c; to destroy the object. However, it masks the fact that Cat was dynamically allocated. If I were reading this code, I wouldn't expect c to be referring to a dynamically allocated object.

You must remember to destroy dynamically allocated objects. Dereferencing the result of a new-expression makes that more difficult to achieve, so avoid it.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
12

This expression:

new Cat();

Creates dynamically an object of type Cat, and you are ignoring the returned pointer (not storing it, not dereferencing, nothing). This expression:

*new Cat();

Does the same as the one above, except that you are also dereferencing the pointer returned by new. But dereferencing a pointer per se is an operation has no side-effect.

Concretely, therefore, the effect of both expressions is the same. The important bit is that you are leaking memory twice by losing the one and only reference to the objects you create dynamically.

Keep in mind that every object created with new must be destroyed by a corresponding call to delete. For instance, if you stored the returned pointer this way:

Cat* pCat = new Cat();

That would allow you to do, later on:

delete pCat;

And avoid memory leaks. Also, this:

Cat& cat = *new Cat();

Would allow you to do, later on:

delete &cat;

And avoid memory leaks again. Notice, however, that this would not be an option:

Cat cat = *new Cat();

The above would still give you a memory leak. The reason is that it would copy the object obtained by dereferencing the pointer returned by new into cat. In other words, cat would be a different object than (although identical to) the one the new expression created.

The object created by the new expression, on the other hand, would be lost - resulting in a memory leak again.

In Modern C++, it is advisable to avoid manual memory management by calling new and delete; rather, consider using smart pointers (which one depends on the ownership policy that you need). For instance:

#include <memory>

// ...

std::shared_ptr<Cat> pCat = std::make_shared<Cat>();

Smart pointers take care of automatically destroying the referenced object when the last smart pointer to the pointed object is destroyed.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • 1
    How do you know he's leaking memory? I use the first form fairly often without leaking memory, at least in specific types of applications. It all depends on what the constructor of `Cat` does. Given that in many applications, the object will be deleted by a `delete this;` in the object, in reaction to some external event, there doesn't seem to be any reason to do anything with the returned value of the operator new. (The constructor has, of course, taken care of an registration for the needed events.) This seems to be the most usual case when `new` is used. – James Kanze Apr 20 '13 at 15:53
  • @JamesKanze: It took me a while to understand what you meant, mostly because you seem to be making a lot of non-assumptions about the OP's question. It seems reasonable IMO to assume from the text that there is nothing like that going on here. There is a regular class in a complete program, and the OP is asking about the difference between `new` and `*new`, so I find it very unlikely that they might have figured out some self-registration, self-deletion, and event-listening pattern in there. – Andy Prowl Apr 20 '13 at 16:06
  • You seem to be making the assumptions. The self-registration/self-deletion pattern is extremely frequent, and should probably be assumed in the lack of additional information. At any rate, just assigning a value you get from `new` to a smart pointer, without any additional information, is a sure recipe for disaster. – James Kanze Apr 20 '13 at 20:08
  • @JamesKanze: Btw, why are you picking on my answer in particular? Everybody here is mentioning memory leaks - and that because it's reasonable to assume that what we see is what the OP has. A simple program with a simple local class that does no event-registering and no self-deletion. – Andy Prowl Apr 20 '13 at 20:11
  • Because I saw it first. The issues are not as evident as most of the responders seem to think. (But the `*new` version is almost certainly an error. Unless he does something with the reference.) – James Kanze Apr 20 '13 at 20:18
6

Does it help you:

Cat *ptr = new Cat();
Cat cat = *new Cat(); /* memory leak :( */
0x90
  • 39,472
  • 36
  • 165
  • 245
  • That makes sense. I'm not using variables though. –  Apr 20 '13 at 15:00
  • Note that the latter copies the new `Cat` into `cat`, then leaks the memory allocated with `new`. – Jerry Coffin Apr 20 '13 at 15:04
  • @JerryCoffin thanks, I mentioned it in the answer – 0x90 Apr 20 '13 at 15:06
  • Of course, if you're allocating the class dynamically, it probably shouldn't support copy, so the second version shouldn't compile. – James Kanze Apr 20 '13 at 20:19
  • @JamesKanze there is always a default `=` operator and copy constructor in c++ which are implemented, so it works but probably won't work as expected. – 0x90 Apr 20 '13 at 20:50
  • @0x90 There is _not_ a default = operator if I declare one (private, and without an implementation). There is _not_ a default + operator if the class inherits from `boost::noncopiable`. Both are widespread and well known techniques for inhibiting assignment, and in actual practice, most classes you would actually allocate dynmically will use one of them. – James Kanze Apr 22 '13 at 07:45
  • @JamesKanze You are right but it is almost as to say there is no war when there is total peace. – 0x90 Apr 22 '13 at 08:38