0

While doing a project dealing with graph theory, I used objects like such:

class Node{
vector<Node> nodeList;
};
Node n = new Node();
Node a = new Node();
n.nodeList.push_back(a);

After creating about 20 nodes each with an average of 3 connections to other nodes, my program would basically hang.

To fix that, I changed my object declarations to

class Node{
vector<Node*> nodeList;
};
Node* n = new Node();
Node* a = new Node();
n.nodeList.push_back(a);

And my program ran through 50 nodes with 10 connections instantly.

The second example ran faster because I was just adding pointers to the lists, as opposed to the actual nodes, right?

But the C++ documentation says that the new keyword returns a pointer to the created object. Why is the entire object put into the vector in the first example as opposed to just the pointer?

Is there any reason the standard in C++ is to copy the entire object into a data structure instead of a pointer?

EDIT: I apologize, you are right the first example should not compile. I don't have the first example anymore on my drive anymore, and I can't remember exactly how it was. Sorry.

Steven Morad
  • 2,511
  • 3
  • 19
  • 25
  • 3
    Did your first attempt even compile??? `new`-operator demands a pointer. – bash.d May 10 '13 at 05:18
  • It compiled and ran, it just got very slow at around the 20th node. All I did to change it was add *'s everywhere. – Steven Morad May 10 '13 at 05:20
  • 3
    Which compiler are you using? `new Node()` returns `Node*` and `Node n` is not the same thing at all. Your fixed version is the correct way to do it. If you want to allocate on the stack, it should've been `Node n` with no `new` required. – tadman May 10 '13 at 05:21

3 Answers3

3

Is there any reason the standard in C++ is to copy the entire object into a data structure instead of a pointer?

Traditionally, all standard library container classes work with Value Semantics as opposed to Reference Semantics.
Values semantics means that containers create internal copies of their elements and return copies of those elements, while Reference Semantics mean that containers contain references to the objects that are their elements. The most obvious way to achieve this by using pointers as container elements. The standard library uses values semantics because:

  • Implementing value semantics is simpler.
  • Reference semantics can be error prone. One needs to deal with the actual object being valid all the time during the life cycle of the container element.
  • If one needs explicit reference semantics then they can choose to do so by using pointers as container elements.

The first code example you show just cannot work as it is. The use of new mandates a pointer. Because this pointer needs to point to the object on freestore. An object with non pointer data type cannot do that. Probably, what you do have in code is assigning a derived class object to a base class object, thus resulting in Object slicing.


If you do need reference semantics it is a good idea to use a smart pointer as container element than the raw pointer you are using now.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

But the C++ documentation says that the new keyword returns a pointer to the created object. Why is the entire object put into the vector in the first example as opposed to just the pointer?

It doesnt, this code:

class Node{
vector<Node> nodeList;
};
Node n = new Node();
Node a = new Node();
n.nodeList.push_back(a);

simply wont compile, you cant assing a pointer to a value or reference variable.

The vector will hold what ever you specify in the template parameter, be a pointer or a whole object (byVal):

vector<Node> nodeList;

This vector will be a collection of Node objects (by value), and you can only push back Node objects by value.

vector<Node*> nodeList;

This is a vector of pointers of type Node, and you can only push back pointers of type node.

AngelCastillo
  • 2,385
  • 2
  • 18
  • 26
1

But the C++ documentation says that the new keyword returns a pointer to the created object. Why is the entire object put into the vector in the first example as opposed to just the pointer?

It's probably not... the only way Node a = new Node(); can compile is if there's a Node(Node*) or Node(const Node*) constructor, which Steven would presumably have told us about by now given the comments.

So - my recent SO mantra - 'show us the code or it didn't happen'. ;-P

Is there any reason the standard in C++ is to copy the entire object into a data structure instead of a pointer?

Containers are designed to have value semantics. That's very flexible, as you can choose to have raw- or any-of-many smart-pointers in the container if that suits your purposes. If the containers were designed to extract and store raw pointers to the objects being push_back()ed then there would be more decisions and necessary inefficiencies. For example, a container of doubles or ints doesn't want to store each one indirectly in separate (non-contiguous) heap memory - that'd have a large performance hit.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252