C ++ публичный адрес конструктора - PullRequest
1 голос
/ 03 апреля 2011

После написания кода ниже:

#include <iostream>

using namespace std;
typedef struct Node {
    int value;

    Node(int index) { 
        value = index;
    }
} Node;

int main() {
    Node* arr[10];
    for(int i = 0; i < 10; i++) {
        arr[i] = &Node(i);
    }
    for(int i = 0; i < 10; i++)
        cout << arr[i]->value << endl;
}

Я видел, что код печатает только 9 вместо всех цифр от 0 до 9, которые должны были быть. После отладки кода я увидел, что адрес arr [i] для каждого i одинаков, и Node (i) освободил место для arr [i] только один раз, и после этого единственное, что value = index без освобождения любое другое пространство. Почему?

Ответы [ 3 ]

6 голосов
/ 03 апреля 2011

Эта строка: arr[i] = &Node(i); хранит указатель на временный объект.Node(i) создает временный объект, который может быть уничтожен в конце оператора, после чего все ссылки на него становятся недействительными, что означает, что результаты любого кода, который разыменовывает arr[i], будут неопределенными.Причина, по которой в этом случае вы получаете все 9, состоит в том, что компилятор оптимизирует код - поскольку за один раз создается только 1 временный Node(i), компилятор просто повторно использует эту память каждый раз в цикле.

Чтобы устранить проблему, выделите память из кучи для каждого объекта: arr[i] = new Node(i);.Затем, когда вы закончите использовать их, вам также нужно будет помнить, чтобы удалить каждый из них:

for (int i=0; i < 10; ++i) {
    delete arr[i];
}

Если вы хотите исследовать дальше, попробуйте добавить код в ваш класс Node, чтобы увидеть, что происходит:Пример распечатайте адрес this в вашем конструкторе и / или создайте деструктор, который просто распечатывает сообщение, чтобы вы могли видеть, как оно вызывается.

5 голосов
/ 03 апреля 2011

Для создания новых объектов используйте new Node(i), иначе вы создаете временные объекты в стеке, поэтому они все одинаковые.

Не забудьте вызывать delete для каждого объекта, который вы получаете от нового.

3 голосов
/ 03 апреля 2011
&Node(i)

Это выражение создает временную переменную и возвращает ее адрес.Затем временный объект уничтожается, и в следующий раз, когда выражение вычисляется, в том же месте создается другой временный объект, отсюда и идентичные адреса.Узел.

#include <iostream>

using namespace std;
typedef struct Node {
    int value;

    Node(int index) { 
        value = index;
    }

    Node() : value( 0 ) {} // allow default construction
} Node;

int main() {
    Node arr[10]; // default-construct array values
    for(int i = 0; i < 10; i++) {
        arr[i] = Node(i);
    }
    for(int i = 0; i < 10; i++)
        cout << arr[i].value << endl;
}

Не используйте new Node для каждого объекта в отдельности. Всегда использовать контейнерный объект для управления группой объектов с похожей семантикой.Вы можете использовать std::vector здесь или std::array, если он у вас есть.Служебная нагрузка, введенная std::vector, будет меньше, чем накладная, введенная new.

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