Reputation: 323
I know that the new operator in c++ always return a pointer to the created object.
class Node {
int data;
Node* next;
public:
Node();//default
Node(int);//parameter
Node(int, Node*);//parameter2
Node(Node*);//copy
~Node();
void setData(int);
void setNext(Node*);
int getData();
Node* getNext();
void display();
};
So that we can do:
Node *n = new Node;
However, I also saw the following code:
Node n2 = new Node;
I tested it myself and I works as well.
What is the reason for this ?
Upvotes: 0
Views: 450
Reputation: 179981
Node(Node*);//copy
isn't a proper copy constructor. A normal copy constructor takes it argument by const reference, i.e. Node(Node const& src)
.
Still, `Node(Node*)
exists, and when you initialize Node n2
with a Node*
from new Node
it's the constructor chosen. It's a perfect match.
If you're working with new
and raw pointers (i.e. not std::unique_ptr<Node>
), watch out for memory leaks. Certainly your public interface should not expose Node*
.
Upvotes: 2
Reputation: 145359
By defining suitable constructors instances of a type can be initialized with just about anything as constructor argument.
In addition, since there is conversion from any raw pointer type to bool
, you can also do
bool x = new Node;
And the language allows much else that might appear baffling at first, e.g.
Node n = n;
The idea is that a C++ programmer prefers having control over being nannied. So in C++ what isn't explicitly forbidden is usually allowed, because in some context it might make sense and be useful. Some other languages are based on different philosophies.
It can often (but not always) be a good idea to declare a constructor with a single argument as explicit
. Then it will not be implicitly invoked. E.g.,
explicit Node( Node* );
Then the declaration
Node n = new Node();
will result in a compilation error.
However, explicit use of that constructor, as in
Node n( new Node() );
will still compile.
Upvotes: 0
Reputation: 33546
It might work only because you have created a really unusual copy constructor:
Node(Node*); //copy
It takes a pointer and creates an object from it. Therefore, your line
Node n2 = new Node;
in fact is a:
Node n2 = Node( new Node() );
Observe the "new Node" returning pointer, and a object constructor Node()
. I think that copy constructor would need to be implicit though, but that's another case.
It is an unusual copy-ctor, because copy-ctors usually doesn't take pointer, and they do that for this very reason: it makes too easy to make stupid errors and typos like forgetting a *
after the type. Usually, they take const-reference to the copied object:
Node(Node const&); //copy
Having it this way, the line
Node n2 = new Node;
would not compile, as there'd be no way to "convert" Node*
to Node
. On the other hand, if you really wanted to have that line working again, you'd need to write:
Node n2 = *(new Node);
or something similar. Still, it's a bad idea, since the recently new
-ed object will never be deleted and will linger in the memory forever (that is, until program exists).
To get that cleaned up:
Node* tmp = new Node;
Node n2 = Node(*tmp);
delete tmp;
but this is approaching a nonsese anyways, since you create a new obejct just to create a new object. This horrible thing should be probably rewritten as simple:
Node n2 = Node();
EDIT: which of course is the same as plain
Node n2;
unless your compiler is real issues :)
Upvotes: 1
Reputation: 1834
Dynamic memory is allocated using operator new.
Node *n= new Node;
allocates space for a single element of type Node
and returns a pointer to it.
Node n2=new Node;
works in this case due to Node()
and Node(Node*)
functions.
Node(Node*)
is doing the implicit conversion from Node*
to Node in this case as the assignment is doing
new Node => Node(new Node) => Node(Node*)
Upvotes: 1
Reputation: 3348
Your code works because your Node class defines a constructor which takes a Node pointer. It is this one:
Node(Node*);//copy
This isn't the correct syntax for a copy constructor by the way, which would be:
Node(const Node& other);
When you assign the new Node
to a node object with Node n2 = new Node;
you are (1) allocating a new Node object on the heap, (2) initialising n2 on the stack by calling the constructor which takes a Node pointer and (3) leaking the heap-allocated Node.
Upvotes: 0
Reputation: 10486
This is a case of implicit constructor conversion.
In this case :
Node n = new Node;
Your Node (Node *);
constructor will be implicitly called.
A more complete explanation can be found here for instance.
You can prevent this from happening by flagging this constructor with they explicit keyword :
explicit Node (Node *);
And now above code won't compile (g++ 4.7.2) :
error: conversion from ‘Node*’ to non-scalar type ‘Node’ requested
You'll have to explicitly call the constructor :
Node n (new Node);
Upvotes: 0
Reputation: 6423
You have a wrong copy constructor:
Node(Node*);//copy
This actually is an implicit conversion from Node*
to Node
, definitely not what you want.
Copy constructor by definition should allow const Node&
in parameter, e.g.:
Node( const Node& );
Please see Copy constructors, assignment operators, and exception safe assignment:
Note that none of the following constructors, despite the fact that they could do the same thing as a copy constructor, are copy constructors:
MyClass( MyClass* other ); MyClass( const MyClass* other );
Upvotes: 0
Reputation: 4812
Node(Node*);//copy
This is NOT a copy constructor and is an implicit conversion from Node* to Node.
The correct prototype for a copy constructor is:
Node(Node const&);
For those of you who like to get riled up about coding style then this is also the same thing:
Node(const Node&);
If you need a copy constructor then it is very likely that you will also require an assignment operator:
Node& operator=(Node const&);
If you have a constructor that accepts a pointer of the same type, it is much safer to make that constructor explicit:
explicit Node(Node*);
This would have trapped your assignment from a pointer to a value type at compile time and possibly prevented the ensuing memory leak.
Upvotes: 2