Несколько способов создать экземпляр класса в c++. В чем разница?

ifstream in1;
ifstream in2();
ifstream *in3 = new ifstream();

В чем разница? Между 2 и 3 еще понятно: один экземпляр хранится на куче, другой в стеке. А что с первым?


#include <iostream>
using namespace std;
class Class
{
public:
    Class() {}
    Class(int a) {}
};
int main()
{
    Class a;
    Class b(4);
    Class c();
    Class *d = new Class();
}

введите сюда описание изображения

Как-то так выглядит аналогичный код на ассемблере. Компилировал с ключом -O0. Хочу заметить, что Class c(); игнорируется компилятором Такой вопрос: где хранится класс и указатель this в (1,2) и 4 случае?


Ответы (2 шт):

Автор решения: AR Hovsepyan

Между 1 и 3 еще понятно: один экземпляр хранится на куче. А второй это прототип функции. Объявление с круглыми скобками будет объявлением объекта лишь в том случаи, если в круглых скобках указаны аргументы конструктора. Объект можно создать также с помощью универсального инициализатора. Объявление fstream in2{};(фигурные скобки) будет идентично fstream in2;

P.S. Что касается третьего объекта, то new ifstream() это конструкция New-expression, для которой круглые скобки хоть и лишние, но допустимые. Это создания объекта в куче, а не объявление...

→ Ссылка
Автор решения: Arenoros

Исправление ответа, спасибо за комментарий @ARHovsepyan.

Плохо посмотрел ассемблерный вывод прежде чем писать.

Во втором случае ты создаёшь не экземпляр объекта, а объявляешь функцию которая возвращает ifstream.

В то же время если передать аргументы то это уже будет вызов конструктора Например пример для std::vector

std::vector<int> arr(5, 10);

в результате arr=[10,10,10, 10, 10];


P.S.

Ещё немного вариантов создания экземпляров:

  • например если использовать фигурные скобки будет вызван конструктор принимающий std::initializer_list:
std::vector<int> arr{5, 10}; // arr = [5,10]
  • Так же возможен вариант с размещающим new
char data[sizeof(std::vector<int>)];
std::vector<int>* arr = new (data) std::vector<int>();
→ Ссылка