В чем разница между использованием `new classObject` и` & classObject` при создании нового объекта? - PullRequest
2 голосов
/ 17 апреля 2020

Ниже приведен мой код, в котором я определил два класса Node и List, которые делают то, что вы думаете, они делают. При расширении списка мне нужно создать новый объект Node (см. строку с комментарием в моем коде ). Если я использую new Node(data), тогда все выглядит нормально, и вывод

2 3 5

Но если я изменю его на &Node(data), вывод будет

7530648 7530648 7530648 7530648 7530648 7530648 7530648 7530648 7530648 7530648 7530648 7530648
7530648 7530648 7530648 7530648 7530648 7530648 7530648 7530648 7530648 7530648 7530648 7530648

(и т. Д .; не заканчивается, пока я не закрою окно)

В чем разница между использованием new Node(data) и &Node(data) здесь? Почему вывод второго случая такой странный?

Обратите внимание, что я использовал опцию -fpermissive для моего компилятора TDM-G CC -64-5.1.0. Хотя это кажется как плохой выбор, я только что понял, что я на самом деле не уверен в том, как долго живет объект Node, созданный выражением Node(data). Надеюсь, этот вопрос будет по-прежнему полезен для тех, у кого может быть такая же путаница.

#include<iostream>
using namespace std;

class Node
{
    int _data;
    Node* _next;
public:
    Node(int data) { _data = data; _next = 0; }
    void setNext(Node* next) { _next = next; }
    Node* getNext() const { return _next; }
    int getData() const { return _data; }
};

class List
{
    Node* _head;
public:
    List() { _head = 0; }
    void add(int data)
    {
        if(!_head)
        {
            _head = new Node(data);
            return;
        }
        Node* temp = _head;
        while(temp->getNext())
            temp = temp->getNext();
        temp->setNext(new Node(data)); // What if I use `&Node(data)` instead of `new Node(data)`?
    }
    void print() const
    {
        Node* temp = _head;
        while(temp)
        {
            cout<<temp->getData()<<" ";
            temp = temp->getNext();
        }
    }
};


int main()
{
    List L;
    L.add(2);
    L.add(3);
    L.add(5);
    L.print();
}

Ответы [ 2 ]

3 голосов
/ 17 апреля 2020

В чем разница между использованием new classObject и &classObject

new classObject Создает новый объект типа classObject с динамическим c хранилищем.

&classObject возвращает адрес объекта, названного идентификатором classObject.

&Node(data)

Это выражение неверно сформировано. Операнд оператора addressof здесь является значением. Это не разрешено. Компилятор не требуется для успешной компиляции программы, и стандарт не описывает, как программа должна вести себя. Вот пример вывода из произвольно выбранного компилятора:

error: taking the address of a temporary object of type 'Node' [-Waddress-of-temporary]
        temp->setNext(&Node(data));
                      ^~~~~~~~~~~

Однако некоторые компиляторы допускают это как расширение языка. В этом случае создается временный объект типа Node. Время жизни временного длится до конца этого полного выражения. Оператор addressof применяется к временному объекту, а результатом является указатель на временный объект. После полного выражения значение указателя будет недопустимым.

Попытка получить доступ к временному элементу за пределами его времени жизни через недопустимый указатель будет иметь неопределенное поведение.

Почему вывод второй случай такой странный?

Поскольку поведение программы не определено.


Node* _next;
void setNext(const Node* next) { _next = next; }

Указатель на const не является неявно конвертируемым на указатель на неконстантный. Это также плохо сформировано. Вот пример выходных данных от произвольно выбранного компилятора:

error: assigning to 'Node *' from incompatible type 'const Node *'
    void setNext(const Node* next) { _next = next; }
                                             ^~~~
2 голосов
/ 17 апреля 2020

new Node(data) и &Node(data) похожи с определенной точки зрения, потому что они оба являются указателями на Node.
В первом случае это Node динамически выделяется и должно быть явно delete d один день или другой.
Во втором случае вы берете адрес (&) временного Node, который автоматически исчезнет в ближайшем будущем; это приводит к использованию висячего указателя (и приличный компилятор должен предотвратить эту ошибку).
Тогда во втором случае ваш алгоритм использует недопустимые данные; таким образом, странное отображение.
(кажется, что все эти временные узлы расположены в одном и том же месте в памяти - один за другим - тогда ваши алгоритмы бесконечно зацикливаются на одном и том же)

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