Ways to instantiate an object and declare constructors

Asked

Viewed 10,606 times

4

In C++ there are several ways to create a constructor and instantiate an object. But there are so many ways I’m confused by the difference of each.

Assuming I have the following class:

using namespace std;
class Carro
{
    private:
        string modelo;
        string marca;
    public:
        Carro(){}
        Carro(string x, string y) { modelo = x; marca = y;}
}

What would be the difference between the following ways of instantiating the object?

Carro carro = new Carro;

Carro carro;

Carro carro();

Carro carro("Astra", "Chevrolet");

Carro *carro = new Carro;    // Usando ponteiro

Carro *carro = new Carro();  // Usando ponteiro

I would also like to know how the : when declaring a constructor, for example:

Carro(string x, string y) : modelo(x), marca(y) {}

2 answers

4


Carro carro = new Carro;

Is not possible.

Carro carro;

Is declaring the type variable Carro but nothing is being assigned to this variable. It is stored in stack.

Carro carro();

Is declaring a function that returns a type Carro. It doesn’t make much sense in this context.

Carro carro("Astra", "Chevrolet");

You are calling a constructor of the class that receives the specified parameters.

Carro *carro = new Carro;

Changes the initialization form. In most cases it makes no difference. There are cases where initialization may occur by default or by value. In this example the result will be the same but depending on how the class is declared, you can initialize differently. I don’t know all the details about this.

Carro *carro = new Carro();

Is allocating in the heap, so you need to create a new memory allocation and the address of this allocation will obviously be assigned to a pointer and not directly to the type.

I put in the Github for future reference.

Understand about stack and heap.

Learn more about builders.

See about overload and method signature.

Allocation and pointer information.

More information why use pointers.

How to decide whether to use pointer.

Similar question with a few more details.

The last question is already another matter and should be another question but I think you can understand in already asked question.

  • In the case of the third, Carro carro(), when I call some method, when compiling I get the following error: error: request for member 'getModelo' in 'carro', which is of non-class type 'Carro(). That would have something to do with the stack?

  • You could, but there’s no way I could know since this method doesn’t exist in the class you showed. But as the mistake is another I imagine who added it later. So yes, there are situations that the class in stack may not function as expected.

  • I found the reason for this error. In fact, what happens in this case is that the compiler interprets carro() as another type of constructor, and not as the default constructor (the default constructor starts with uppercase). The compiler will interpret as default constructor only if the parentheses are omitted, which is the case for the second option (Carro carro;). I found the solution here: http://stackoverflow.com/questions/877523/error-request-for-member-in-which-is-of-non-class-type

  • Yeah, there’s that too, but you were talking about things that aren’t even present in what you posted. This is not the case for the former because she is trying to allocate heap, not happening is confusion. But the first one is wrong because it is trying to play a pointer as class value.

4

There are some minor nuances left to explain, so I leave here some comments.

For your example

using namespace std;
class Carro
{
    private:
        string modelo;
        string marca;
    public:
        Carro(){}
        Carro(string x, string y) { modelo = x; marca = y;}
}
  • Car car = new car;

    • This statement is invalid/syntax is not valid in C++
  • Car;

    • Declares a Car type variable in the local scope (Scope), usually in the stack, which will be automatically destroyed when the scope (Scope) ends.
  • Car();

    • Declares not a variable but yes a function no arguments, which returns an object of type Car. This is the reason why you get the following error message: error: request for member 'getModelo' in 'carro', which is of non-class type 'Carro(). It’s easy now to understand why the mistake.
  • Car car("Astra", "Chevrolet");

    • Declares a Car type variable in the local scope (Scope), usually in the stack, which will be automatically destroyed when the scope (Scope) ends. Unlike the second example, the default constructor will not be executed here, but the constructor that takes two arguments.
  • Car *car = new car; // Using pointer

    • Default constructor call (default startup)
  • Car *car = new car(); // Using pointer

    • Default constructor call (value initialization)

In the last two examples the difference is related to the initialization of the members of the class, but for your example in particular, there is no practical difference. Instructions allocate a memory space by calling the operator new() and implicitly call the constructor Carro::Carro(), with the sharpener this pointing to a space in that memory (returned by new()). This address is then stored in the pointer carro (stack). Since the allocated memory is not automatically released when the scope ends, it is necessary to perform the memory management manually through the instruction delete.

If you want to read more about the difference between

Carro *carro = new Carro;    // Usando ponteiro
Carro *carro = new Carro();  // Usando ponteiro

You can read the language standard itself:

To zero-initialize an Object of type T Means:
- if T is a scalar type (3.9), the Object is set to the value of 0 (zero) converted to T;
- if T is a non-union class type, each Nonstatic data Member and each base-class subobject is zero-initialized;
- if T is a Union type, the Object’s first named data Member is zero-initialized;
- if T is an array type, each element is zero-initialized;
- if T is a Reference type, no initialization is performed.

To default-initialize an Object of type T Means:
- if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is Ill-Formed if T has no default accessible constructor);
- if T is an array type, each element is default-initialized;
- otherwise, the Object is zero-initialized.

To value-initialize an Object of type T Means:
- if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is Ill-Formed if T has no accessible default constructor);
- if T is a non-union class type without a user-declared constructor, then Every non-static data Member and base-class Component of T is value-initialized;
- if T is an array type, then each element is value-initialized;
- otherwise, the Object is zero-initialized

A program that calls for default-initialization or value-initialization of an Entity of Reference type is Ill-Formed. If T is a cv-Qualified type, the cv-unqualified version of T is used for These Definitions of zero-initialization, default-initialization, and value-initialization.

This is another of the C++ gems that we all love. :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.