Ways to instantiate an object and declare constructors

3

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 one.

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 : works when declaring a constructor, for example:

Carro(string x, string y) : modelo(x), marca(y) {}
    
asked by anonymous 20.09.2015 / 18:02

2 answers

3
Carro carro = new Carro;

Not possible.

Carro carro;

You are declaring the variable of type Carro but nothing is being assigned to this variable. It is stored in the stack itself.

Carro carro();

You are declaring a function that returns a type Carro . It does not 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 startup form. In most cases it makes no difference. There are cases that 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, it can initialize differently. I do not know all the details about this.

Carro *carro = new Carro();

You are allocating 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. p>

Understand stack and heap .

Learn more about builders .

View about overloading and signing the method .

Allocation information and pointers .

More information because using pointers .

How to decide whether to use pointer .

Similar question in more detail .

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

    
20.09.2015 / 18:27
3

There are a few nuances left to explain, so I'll leave some comments here.

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 Car;

    • Declare a variable of type Car in the local scope, usually in the stack, which will be automatically destroyed when the scope expires.
  • Car Car ();

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

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

    • Default builder call (default boot)
  • Car * car = new Carriage (); // Using pointer

    • Default builder call (value initialization)

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

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 accessible default 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 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 one more of the gems of C ++ that we all love. :)

    
20.09.2015 / 19:22