0

We all know, that the simplest way to define a new instance in C++ is the next:

ClassName *obj = new ClassName();

But such a way is bad and more advanced people use smart pointers like: shared_ptr, unique_ptr etc... But if to look at their sources you may find that smart_pointers are using pointers for the creating new instances, not references.

Also I know, that using pointers is not only a bad stuff for a clean source code in C++ (design rules), but also pointers do allocate new memory, because any pointer is a void* type. The correct size depends on CPU architecture, but for the example let's take x86, it holds 4 bytes.

It's rather expensive to use, than using references &, which don't require any memory allocations for them, and that's why to use references in C++ self-defined methods is miles better.

So telling you all this info, I wonder:

Is it possible to define a new instance with a reference in C++ or not? If no, then why?

6 Answers6

6

I am afraid your post is one misconception after another. So the first thing you have to do is throw away all the "books" you've read and read a good book on C++

Now, to try to answer your question. You cannot create an object "with reference". It's the other way around - you can create a reference to an existing object.

MyClass myobject;
MyClass& myreference = myobject;

Just like you can create a pointer to point to an existing object (or not point to anything). Do note that it's not the pointer that created the object. The new-expression does:

new MyClass;

created a new object of MyClass type "on the heap", if you will. But it's quite useless since you've lost all handles to it. You cannot access it. That's why we store the address of this object (which new returns) in a pointer. If it's a smart pointer instead of a plain one, it will automatically "know" when to free the memory, i.e. delete the object, depending on the type of the smart pointer. This said, you can, instead of storing the address of the newly created object, create a reference to it:

MyClass& ref = *new MyClass;
...
delete &ref;

It is also not true that references come for free (in terms of memory). Sure, sizeof(reference) will return the size of the object referred to, but most implementations will use pointer-like logic for references underneath the hood.

Community
  • 1
  • 1
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • Thanks for the great answer! But I have a question about your words *but most implementations will use pointer-like logic*. What are those implementations in real practice? I need a real example. Thanks again! –  Jul 06 '13 at 11:35
  • @GeloVolro: What I mean is that in the end both pointers and references will end up being pointers on assembly-level. – Armen Tsirunyan Jul 06 '13 at 11:42
  • @GeloVolro: most common examples are: gcc, MVSC, and Clang. When we say an *implementation* of the language, we are talking about a compiler. C++ only specifies a *behaviour* that references must meet. To obtain this behaviour, the aforementioned compilers will use (as far I know, maybe there are special cases) the same generated binaries as if you used pointers. That's why we say that references are implemented using *pointers under the hood*. – Boris Dalstein Jul 06 '13 at 11:47
  • Good answer but I think it should start off by addressing the misconception given in the question's very first paragraph. Everything follows on from that. – Lightness Races in Orbit Jul 06 '13 at 13:28
3

We all know, that the simplest way to define a new instance in C++ is the next:

ClassName *obj = new ClassName();

No, we don't... because it's not.

To create a new instance of type ClassName, simply write:

ClassName obj;

Only use dynamic allocation when you need to!

But such a way is bad and more advanced people use smart pointers like: shared_ptr, unique_ptr etc... But if to look at their sources you may find that smart_pointers are using pointers for the creating new instances, not references. Also I know, that using pointers is not only a bad stuff for a clean source code in C++ (design rules)

Which design rules? There are no "rules", only different sets of guidelines written by different people, all with their own views.

I would generally advise avoiding using pointers, because their use implies dynamic allocation, which is more difficult to manage. Smart pointers do help with this, but they are not a reason to use dynamic allocation where you otherwise would not.

also pointers do allocate new memory, because any pointer is a void* type. The correct size depends on CPU architecture, but for the example let's take x86, it holds 4 bytes.

Well, that's not true either. Each pointer type is its own type, and they are not necessarily all the same width. Usually, though, this can be the case.

It's rather expensive to use, than using references &, which don't require any memory allocations for them, and that's why to use references in C++ self-defined methods is miles better.

Nope, also not true. Reference syntax in C++ hides dereference operations by performing them transparently, but you'll find that all implementations/toolchains/compilers implement references using pointers anyway.

You should stop thinking about "pointers" versus "references". Perhaps you're thinking of Java.

You should think of automatic storage duration ("the stack") vs dynamic storage duration ("the heap") — the former is more efficient as it does not require dynamic allocations, but you lose the ability to finely control the lifetime of your object.

Is it possible to define a new instance with a reference in C++ or not? If no, then why?

If by this you mean "how do I create an object without dynamic allocation", refer to the below example:

// automatic storage duration - cheap!
ClassName obj;

// dynamic storage duration - marginally more expensive,
// and now you have to `delete` it, too
ClassName* ptr = new ClassName;

In C++, a reference is like an "automatic pointer"; it does the same job, but without all the syntax requirements:

ClassName* ptr = &obj;  // a pointer to obj
ClassName& ref = obj;   // a reference to obj

The new operator always gives you a pointer to the dynamically-allocated object, never a reference. This is just the way it is.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 1
    Very good answer, thank you very much! But one phrase is still confusing me, quote: *Well, that's not true either. Each pointer type is its own type, and they are not necessarily all the same width. Usually, though, this can be the case.* Any pointer is a `void*` type, isn't it? –  Jul 06 '13 at 15:53
  • Also, if you would be so generous, I want you review my comment at the Waldermort's answer about reference size. Just don't want to repeat the same subquestion here, thanks! –  Jul 06 '13 at 16:00
  • @GeloVolro: No. A pointer-to-`int` has type `int*`, and `int*` is a different type to `void*`. They are distinct pointer types. You can generally convert between the different pointer types, though (until you start talking about pointers-to-members and function pointers, anyway); in C these conversions were implicit; in C++ you have to cast. – Lightness Races in Orbit Jul 06 '13 at 18:15
2
ClassName *obj = new ClassName();

This is not the simplest way. This is :

ClassName obj;

And since a reference is... well, a reference, you must have instantiated an object in order to have a reference.

ClassName obj;
ClassName& refObj = obj;

References as you want to use them can't be created without an object to refer to.

JBL
  • 12,588
  • 4
  • 53
  • 84
1

We all know, that the simplest way to define a new instance in C++ is the next:

No! The simplest way to create an instance is:

ClassName obj;

To initialize a reference for this just say:

ClassName& objRef = obj;

or

const ClassName& constObjRef = obj;

Take care when using references as return values from functions. You should be sure the referenced object instance still exists, when the function leaves it's scope.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
1

I think it is worth it to rectify the different wrong assertions in your post (in addition to answer the main question), so that you can get back on the right track.

The simplest way to define a new instance is A * a = new A();

No. The simplest way is A a;

Such a way is bad, so more advanced people use smart pointers

Indeed, it is not the most recommended. The main drawbacks are:

  1. The objects are allocated on the heap, which makes access slower.

  2. You have to manage the memory yourself, by calling delete explicitely.

Using smart pointers only solves point 2. That's why more advanced people would in fact use as much as possible allocation on the stack, using A a;. However, this is not always possible, in such case a smart pointer is indeed the best option.

But smart pointers are using pointers, not references!

Indeed, the point of smart pointer is only to help with memory management (that's why the header is #include <memory>), so they do deal with objects on the heap, not on the stack. What they do is calling delete for you, so you don't have to worry about memory leak.

Pointers are bad because any pointer is a void* type, that takes memory

Yes, a pointer takes N bits of memory (N=32 or 64 depending on your architecture) in the stack + the actual size S of the object in the heap. But this is also true for references! Summary of the space required for different kind of entities:

  • Pointers (A * a = new A;): N bits on the stack (address) + S bits on the heap (object)

  • References (A a; A &ref = a;): N bits on the stack (address) + S bits on the stack (object)

  • Direct values (A a;): S bits on the stack (object)

So to the point of view of memory space, references and pointers are the same, you only have a gain if you use direct values on the stack. Note that in fact, a reference can also point to an object on the heap (A &ref = *new A;) and a pointer can also point to an object on the stack (A a; A * ptr = &a;).

Is it possible to define a new instance with a reference in C++ or not?

Yes:

A a; 
A &ref = a;
Boris Dalstein
  • 7,015
  • 4
  • 30
  • 59
0

it is not a good idea to return by reference in C++.(I think you meant this). Because, you can not return local variables to the function by reference. referencing the link:

int& DoubleValue(int nX)
{
    int nValue = nX * 2;
    return nValue; // return a reference to nValue here
} // nValue goes out of scope here

"...The function is trying to return a reference to a value that is going to go out of scope when the function returns. This would mean the caller receives a reference to garbage..."

fatihk
  • 7,789
  • 1
  • 26
  • 48