C ++, причина конструкторов - PullRequest
3 голосов
/ 18 декабря 2010

У меня два вопроса.

1) Что на самом деле делает конструктор? Что произойдет, если мы не используем конструкторы при объявлении экземпляра?

2) Можете ли вы сказать мне разницу между этими двумя?

A a(1,2)

A *a = new A(1,2)

С уважением.

Ответы [ 5 ]

8 голосов
/ 18 декабря 2010

Конструктор инициализирует переменные-члены класса, чтобы он был готов к использованию.Результат неиспользования конструктора при объявлении экземпляра зависит от контекста.

Если вы выделяете переменную в куче, например:

A *a;

a будет указывать наслучайный адрес в памяти, пока он не будет присвоен NULL или 0, или существующему или новому экземпляру класса, например:

A *a = new A(1, 2);

Если вы размещаете переменную в стеке, используется следующий синтаксис:

A a(1, 2); // if parameters are used
A a; // if no parameters are used

Оба из вышеперечисленных вызывают конструктор класса A, размещая его экземпляр в стеке.Итак, это отвечает на оба ваших вопроса - ваш первый пример выделяет экземпляр A в стеке, а второй выделяет экземпляр A в куче.

3 голосов
/ 18 декабря 2010

Конструктор - это функция с тем же именем, что и класс. Основная цель конструктора - инициализировать переменные-члены вновь созданного объекта некоторыми значениями по умолчанию. Также могут вызываться другие функции инициализации.
Как и другие функции в C ++, конструкторы могут быть перегружены. (Перегруженная функция - это новая версия существующей функции с другими аргументами). Например, рассмотрим следующий класс Point с тремя конструкторами:

class Point
{
public:
    Point() : x_(0), y_(0) { }
    Point(int x, int y) : x_(x), y_(y) { }
    Point(const Point& p) : x_(p.x), y_(p.y) { }
private:
    int x_;
    int y_;
};

Первый конструктор инициализирует координаты нулями, а второй позволяет пользователю указать их значения по умолчанию:

void create_and_destroy_points ()
{
   Point p1; // => x_ = 0, y_ = 0
   Point p2(100, 200); // x_ = 100, y_ = 200
}

При объявлении таким образом эти Point объекты размещаются в стеке . Это означает, что выделенная им память будет автоматически освобождена при возврате функции create_and_destroy_points. Другими словами, p1 и p2 бесполезны вне функции.
Объекты также могут быть размещены в куче 1017 *. Это распределяет объекты во время выполнения, и они могут затем выживать при различных вызовах функций. Они назначаются с ключевым словом new и продолжают действовать, пока не будут освобождены с delete. Невозможность удалить выделенный объект кучи после его использования приведет к утечке памяти .

Point* create_point ()
{
   Point* p = new Point(100, 200);
   return p;
}

Point* p = create_point();
// use p 
delete p;

Третий конструктор - это конструктор копирования . Он вызывается, когда новый объект создается путем копирования другого объекта:

Point p1;
Point p2 = p1; // calls the copy constructor for p2 with p1 as argument.
Point p3(p1);  // alternate syntax
2 голосов
/ 18 декабря 2010

1) Конструкторы должны использоваться исключительно для инициализации переменных-членов.

class A {
public:
    A() { a = 0; b = 0; }
    A(int a, int b) { this->a = a; this->b = b; }

private:
    int a;
    int b;
};

В вышеприведенном классе у нас есть два конструктора, каждый из которых инициализирует переменные-члены, один с нулями, а другой сзаданные аргументы.

Класс может иметь любое количество конструкторов.При создании экземпляра класса вы всегда должны вызывать один из них, например:

A a1;    // uses first constructor, i.e. A::A() 
A a2();  // also uses first constructor

A* a3 = new A(1, 2); // uses second constructor, i.e. A::A(int a, int b) 
A a4(1, 2);          // also uses second constructor

2) Объявление:

A a(1, 2)

объявляет переменную, которая содержит экземпляр, связанный с областью действия, что означает, чтоЭкземпляр будет автоматически удален при выходе программы из этой области.Например:

void fn() {
    A a(1, 2);
    ...
    ...
}

в начале экземпляра функции создается, который будет автоматически удален при выходе из этой функции.

В случае:

A *a = new A(1,2)

объявлена ​​переменная a, и она указывает на вновь созданный экземпляр A. Вы должны вручную удалить экземпляр, на который указывает точка, с помощью «delete a», но ваш экземпляр может остаться в области действия, в которой объявлен объект.Например:

A* fn()
{
    A *a = new A(1,2)
    return a;
}

здесь функция fn возвращает экземпляр, созданный внутри своего тела, т.е. экземпляр сохраняется в области действия функции.

2 голосов
/ 18 декабря 2010

1) Что на самом деле делает конструктор?

Конструкция объекта состоит из двух частей:

  1. Выделение необходимого количествапамять

  2. Выполнение кода в конструкторе

Что произойдет, если мы не используем конструкторы при объявлении экземпляра?

Конструкторы всегда выполняются, даже если вы их явно не вызываете.Например:

std::string a;

Здесь будет вызываться конструктор по умолчанию для класса строки.

2) Можете ли вы сказать мне разницу между этими двумя?

A a(1, 2);

Этот код вызывает пользовательский конструктор.

A a;

Этот код вызывает конструктор по умолчанию.

2 голосов
/ 18 декабря 2010

Чтобы ответить на вопрос №2, ваш первый пример выделяет переменную 'a' типа A в стеке, а ваш второй пример выделяет указатель '* a' для типа A. Указателю дается начальное значение, адрес, которыйуказывает на динамическую память.В обоих случаях вызывается конструктор A :: A (), принимающий 2 параметра

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...