Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

in C++, what's the difference between an object and a pointer to an object?

In java and objective-c, a variable representing an object is generally a pointer to that object. However, it seems that in C++, it's common to have non-pointer types hold objects. What's the difference between the two?

If I pass a struct as an argument to a function, I believe I'm passing by value, meaning I'm actually creating a new struct in memory, and changes to that struct inside the function its passed to won't affect the "source" struct outside the function. However, if I pass a pointer to a struct, there's still only one original struct, and changes to the struct referenced by the pointer will be visible to any code which is aware of this struct. Do I have that right?

So, is there any difference with objects? When I pass a non-pointer object to a function, does the entire object get copied?

like image 460
morgancodes Avatar asked Mar 21 '11 00:03

morgancodes


People also ask

What is the difference between object and pointer object in C++?

In C++, a pointer holds the address of an object stored in memory. The pointer then simply “points” to the object. The type of the object must correspond with the type of the pointer.

What is a pointer to an object?

A pointer is a type of variable that carries location information. In this case, the example variable will store the address of an Order object that we want to interact with. We initialize the pointer variable by using the C++ new operator to construct a new object of type Order.

Are pointers considered objects?

In computer science, a pointer is an object in many programming languages that stores a memory address. This can be that of another value located in computer memory, or in some cases, that of memory-mapped computer hardware.

What is the difference between pointer and variable?

A pointer variable (or pointer in short) is basically the same as the other variables, which can store a piece of data. Unlike normal variable which stores a value (such as an int, a double, a char), a pointer stores a memory address. Pointers must be declared before they can be used, just like a normal variable.


2 Answers

It's exactly as you said.

When you pass an object by value, its copy constructor is invoked to produce a new instance of such object that will be used inside the function. The changes done to such new object won't be reflected to the original one1.

As with structures, the default copy constructor just does a shallow copy of the original object - i.e., its fields are copied2 to the new instance; in many cases this is not desirable (e.g. if the object wraps a pointer/another resource), so there are classes which redefine the copy constructor or disable it completely. Objects of these last classes can only be passed by pointer or reference.

Passing objects by value can be costly if they are bigger than a pointer (in size) or in general if their copy constructor isn't "cheap". On the other hand, in comparison to pointers, the pass-by-value yields the usual advantages of not having to specify the pointer ownership, letting the callee do whatever it wants with the object, etc.

Notice that passing an object by value kills the polymorphism. This because a function receiving an object by value receives a statically typed object, with a precise size and type, so any attempt to pass an object of a derived class will result in object slicing (the copy constructor for the base class is called, that by default just copies the fields that are available in the base class).

This is the reason why often the preferred method of passing objects is by const reference. This yields several advantages:

  • no copies involved; the object that the callee will see will be exactly the one specified at the moment of the call;
  • no changes to the original object can be made, thanks to the const qualifier;
  • if however the callee needs to change a copy of the object, it can still construct a copy by itself from the reference;
  • no awkward pointer syntax;
  • polymorphism preserved, since behind the scenes we're actually passing a pointer;
  • no big doubts about object ownership: the general rule about references is that they are owned by the caller.

  1. As far as the "raw fields" of the object are concerned; naturally if the original object and the copy continue to share a pointer/handle to the same resource some modifications to one may affect the other.

  2. Primitive types (and in general PODs) are copied bitwise, while the copy constructor is called for non-POD types.

like image 134
Matteo Italia Avatar answered Nov 13 '22 00:11

Matteo Italia


The difference mostly has to do with where in memory an object is allocated. For instance:

int main() {
    MyObject x;   //allocates space for an instance of MyObject on the stack
    MyObject* y;  //allocates space for a pointer on the stack
    MyObject* z = new MyObject();  //allocates space for a pointer on the 
                                   //stack and an object instance in the heap and
                                   //sets the pointer to point to the new instance
    MyObject* a = &x;  //allocates space for a pointer on the stack and 
                       //makes it point to 'x'
    ...
}

int someFunc(MyObject byValue, MyObject* byReference) {
   //the 'byValue' parameter will be passed by creating a copy of the 
   //entire source object on the stack (can be quite expensive for 
   //complex object types)

   //the 'byReference' parameter will be passed by creating a 
   //copy of the source pointer on the stack and setting it to 
   //point to the source object in memory
}
like image 31
aroth Avatar answered Nov 12 '22 23:11

aroth