Почему шаблон C++ возвращает шестнадцатеричное значение?

У меня есть простой класс C++, который использует общие шаблоны для хранения и извлечения общих переменных. Сохранение их не проблема, но возврат универсальной переменной возвращает шестнадцатеричное значение.

Может ли кто-нибудь сказать мне, почему это происходит?

Узел.h

#pragma once
#include <iostream>

template <typename T>
class Node {
    private:
        T data;
        Node *next_node;

    public:
        Node(T data) {
            this->data = data;
            std::cout << "Node with data - " << this->data << " - has been created." << std::endl;
        }
        
        T get_data() {
            return this->data;
        }
        
        void set_next_node(Node next) {
            this->next_node = next;
        }

        Node get_next_node() {
            return this->next_node;
        }
};

Main.cpp

#include <iostream>
#include "node.h"

int main() {

    Node node = new Node("Hello World");

    std::cout << "Node data: " << node.get_data() << std::endl;

    return 0;
}

Выход

gabriel@desktop:/media/gabriel/main/repositories/CPP Sandbox/nodes$ g++ main.cpp -o main
gabriel@desktop:/media/gabriel/main/repositories/CPP Sandbox/nodes$ ./main
Node with data - Hello World - has been created.
Node with data - 0x55ec552d3eb0 - has been created.
Node data: 0x55ec552d3eb0


Код, который вы показываете, и вывод, который вы показываете, не совпадают. Ваш код даже не скомпилируется Пожалуйста, предоставьте минимальный воспроизводимый пример

ChrisMM 22.02.2023 18:12

Как вы думаете, что такое T? и очень связано с этим, почему вы используете new?

463035818_is_not_a_number 22.02.2023 18:12

@ChrisMM Что вы имеете в виду, что вывод не совпадает? Я обновил вопрос.

Gabriel Gavrilov 22.02.2023 18:13

Вам удалось скомпилировать Node x = new Node, +1 за это. Это интересный случай максимальной путаницы, вызванной бессмысленным использованием new.

463035818_is_not_a_number 22.02.2023 18:14

Текст в нем отличается от вывода. Таким образом, они не могут быть связаны.

ChrisMM 22.02.2023 18:14

@ChrisMM компилируется, есть два разных экземпляра Node

463035818_is_not_a_number 22.02.2023 18:15

@ 463035818_is_not_a_number, ты прав. Внимательнее надо было читать. Однако вывод по-прежнему не совпадает с кодом.

ChrisMM 22.02.2023 18:15

@ 463035818_is_not_a_number Вы правы. Удаление нового исправило это. Когда я должен использовать new при запуске класса? (Я все еще изучаю C++, так что, пожалуйста, потерпите меня).

Gabriel Gavrilov 22.02.2023 18:16

Первая строка кода OP в их main эффективно делает это: Node node{ new Node("Hello World") };. Таким образом, создаются два узла, один из которых имеет тип шаблона Node*.

Adrian Mole 22.02.2023 18:16

Ммм ... Я никогда не думал, что вывод аргумента шаблона класса может иметь эту конкретную ошибку. C++ и его новые свойства становятся «лучше» с каждым днем.

StoryTeller - Unslander Monica 22.02.2023 18:18

Я не думаю, что дубликат подходит. В этом коде происходит гораздо больше. И адрес не из печати массива. Проголосовать за открытие

463035818_is_not_a_number 22.02.2023 18:18

Как вы думаете, какое значение имеет T для node? std::string? const char[12]? На самом деле у вас есть Node<Node<const char*>*>.

Nathan Pierson 22.02.2023 18:19

Вау, эта строка Node x = new Node очень запутанная, я думаю, она заслуживает фактического ответа.

pptaszni 22.02.2023 18:21

«Эта строка» — результат того, что кто-то, кто знает C# или Java, пытается изучить C++ и предполагает, что C++ работает так же. Это не так.

Sam Varshavchik 22.02.2023 18:29

Самое смешное, что можно написать еще один конструктор и руководство по дедукции, которое заставит Node x = new Node делать «правильные вещи». Наконец-то можно написать это на C++. Ууууу. Я не думаю, что это то, что они имели в виду, когда представляли ctad :D

463035818_is_not_a_number 22.02.2023 18:34

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

463035818_is_not_a_number 22.02.2023 19:11
Ускорьте разработку веб-приложений Laravel с помощью этих бесплатных стартовых наборов
Ускорьте разработку веб-приложений Laravel с помощью этих бесплатных стартовых наборов
Laravel - это мощный PHP-фреймворк, используемый для создания масштабируемых и надежных веб-приложений. Одним из преимуществ Laravel является его...
Что такое двойные вопросительные знаки (??) в JavaScript?
Что такое двойные вопросительные знаки (??) в JavaScript?
Как безопасно обрабатывать неопределенные и нулевые значения в коде с помощью Nullish Coalescing
Создание ресурсов API Laravel: Советы по производительности и масштабируемости
Создание ресурсов API Laravel: Советы по производительности и масштабируемости
Создание API-ресурса Laravel может быть непростой задачей. Она требует глубокого понимания возможностей Laravel и лучших практик, чтобы обеспечить...
Как сделать компонент справочного центра с помощью TailwindCSS
Как сделать компонент справочного центра с помощью TailwindCSS
Справочный центр - это веб-сайт, где клиенты могут найти ответы на свои вопросы и решения своих проблем. Созданный для решения многих распространенных...
Асинхронная передача данных с помощью sendBeacon в JavaScript
Асинхронная передача данных с помощью sendBeacon в JavaScript
В современных веб-приложениях отправка данных из JavaScript на стороне клиента на сервер является распространенной задачей. Одним из популярных...
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Отказ от ответственности: Эта статья предназначена только для демонстрации и не должна использоваться в качестве инвестиционного совета.
2
16
101
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Без CTAD строка в main выглядит так:

Node<Node<const char*>*> node = new Node<const char*>("Hello World");

Я не уверен, что вы на самом деле хотели, но я уверен, что это не это.

Напечатанный адрес является значением Node<const char*>* члена Node<Node<const char*>*>.

Ответ принят как подходящий

Проблема, с которой вы столкнулись, заключается в том, что вы используете new для создания узла, но затем пытаетесь присвоить указатель, возвращаемый переменной Node без указателя.

Эта строка является проблемой:

Node node = new Node("Hello World");

Что это делает, так это сначала создает безымянный объект Node с типом шаблона const char *; затем, используя указатель на этот новый объект для инициализации вашей переменной node, вы создаете второй объект Node с выведенным типом шаблона Node*. Строки cout, показывающие шестнадцатеричные значения, правильно отображают значение адреса, хранящееся во второй переменной с именем Node.

Вы можете обойти это несколькими способами. Проще всего не использовать оператор new:

Node node{ "Hello World" }; // Construct object directly

Другой способ — продолжить использовать вызов new, но затем сделать node указателем:

int main() 
{
    Node<const char*>* node = new Node("Hello World"); // Or auto node = new Node("Hello World");
    std::cout << "Node data: " << node->get_data() << std::endl; // Now we need "->" instead of the "."
    delete node;
    return 0;
}

Первая строка кода в вашей функции main фактически делает следующее:

Node node{ new Node("Hello World") };

Таким образом, создаются два узла, один из которых имеет тип шаблона Node<const char*>*. Или, другими словами, ваша первая строка эквивалентна следующей с явными типами шаблонов:

Node< Node<const char*>* > node = new Node<const char*>("Hello World");

Также обратите внимание, что оператор = здесь не присваивание, а инициализация; вот почему вызывается конструктор.

Спасибо, что помогли мне решить проблему и объяснили мне, что я делаю неправильно!

Gabriel Gavrilov 22.02.2023 18:29

Другие вопросы по теме