tags:

views:

152

answers:

5

Dumb question, but whenever you call new, do you always have a pointer?

SomeClass *person = new SomeClass();

And is that because you need a pointer to point to that new space of memory that was allocated for the SomeClass variable person? Thanks!

+5  A: 

If new completes successfully, it always returns a pointer (if it doesn't complete successfully, an exception is thrown, and nothing is returned).

The pointer is to the object that was created, or in the case of an array, a pointer to the first element of the array.

James McNellis
A: 

The new expression returns a pointer, but you can use it with "smart pointer" classes (e.g. from Boost). So:

boost::shared_ptr<SomePerson> person(new SomePerson);

I should also point out that, though you may be used to using the parentheses if you come from a Java background, in C++, the parentheses are not needed when using the default constructor. So, for example, one ordinarily writes new T when default constructing, but one writes new T(param), or new T(param1,...,paramN) when constructing an object using a constructor other than the default.

Yes, that is correct; one could, theoretically, write (new SomePerson)->doSomething(), but that would be a memory leak; C++ does not have garbage collection, so it is necessary to store the result of the new expression in something (a pointer or a smart pointer) so that it can be properly deallocated.

Michael Aaron Safyan
Note that `new T` and `new T()` have different results for POD types and class types without any user-declared constructors: `new T()` will value initialize the object, while `new T` will not.
James McNellis
@James, yes, I am aware of that; however, SomePerson is most likely a class.
Michael Aaron Safyan
Whether or not empty parens matter in a `new` expression is one of C++'s little nightmares: http://stackoverflow.com/questions/620137/do-the-parentheses-after-the-type-name-make-a-difference-with-new/620402#620402
Michael Burr
+1  A: 

Yes, always a pointer. Even if you want to overload new, return type must be void*.
And you are right about purpose

Alexander Malakhov
A: 

Yes. If you are asking why it doesn't return a reference instead, since references are nicer than pointers, the answer is historical heritage.

When C++ was in development, if the machine was unable to get memory for the object, a special pointer NULL was returned. This is how it is done in C:

SomeClass *person;
person = (SomeClass*) malloc( sizeof( SomeClass ) );
if ( person == NULL ) fprintf( stderr, "no more people allowed!" );

In standard C++, errors are returned by exception instead:

try {
    SomeClass *person = new SomeClass;
    // do something
} catch ( std::bad_alloc ) {
    std::cerr << "no more people!" << std::endl;
} catch ( ... ) {
    // using exceptions allows for other errors
    // from inside SomeClass::SomeClass too
}

You can still do it the old-fashioned way, though, with nothrow:

SomeClass *person = new( std::nothrow ) SomeClass;
if ( person == NULL ) std::cerr << "no more people allowed!" << std::endl;

The upshot is, this is perfectly reasonable and good style:

SomeClass &person = * new SomeClass; // don't need no stinkin pointers!
Potatoswatter
**SomeClass ** - I don't think is a good style, because you use it as automatic variable and still have to remember to delete it in the end of scope. Straight way to mem-leaks, IMO. And a big surprise for one who will maintain your code
Alexander Malakhov
I think most would consider the last example bad style. While you can get the pointer back at some point, it becomes less clear that the object is dynamically allocated and must be deleted. You also have to worry about the day when somebody replaces the reference type with a base-class in a multiple-inheritance situation -- then you might not be able to get the allocated pointer back at all!
Nick Meyer
@Alexander, @Nick: using `new` if the object isn't going somewhere outside local scope is **bad design**, and no amount of style can compensate for that.
Potatoswatter
@Nick: A base reference is no different from a base pointer in terms of the casts you can use — except then dynamic casts throw instead of returning `NULL`, which is A Good Thing.
Potatoswatter
The local scope issue you raise is exactly why I wouldn't recommend this. If you're going to pass this object on to some other part of your program, it should be clear who must delete it. Most functions that take ownership of objects and delete them when they are no longer needed take pointers. This breaks from that convention, and makes it much less clear what is going on.
Nick Meyer
To clarify the multiple-inheritance comment, if SomeClass derives from BaseClass and SomeClass has multiple bases, the address of the SomeClass part of the object and the BaseClass part of the object may not be the same. If a maintainer comes along and starts to use the object polymorphically, the code which takes the address of the reference and tries to delete it is now no longer correct, because it's deleting an address that's different from the one `new` returned. As Alexander said, that's a big surprise.
Nick Meyer
@Potatoswatter: you are totally right about heap-objects. But it's not about design (which is entities, relations, etc). It's ignorance or folly otherwise, I think )
Alexander Malakhov
@Nick: There's no reason those things can't take and store references. Conversely, taking a pointer doesn't unequivocally mean adoption. There always must be other idioms or documentation to indicate what's going on. On the other hand, pointers always allow reassignment and uninitialized/NULL state. *That* is what seeing one indicates.
Potatoswatter
Potatoswatter
A: 

new creates an object on the heap and all it can return is its address - a pointer.

Nemanja Trifunovic