С++: получение случайных символов в качестве вывода, не знаю, почему

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

Ожидаемый результат: JoeUPSReminderPick up your package! 54,23

Я получаю <, но все, что после этого, - тарабарщина. Любая помощь будет оценена по достоинству.

#include <cstddef>        // for std::size_t
#include <iostream>
#include <memory>
#include <ostream>
#include <string>
#include <utility>        // for std::move, std::forward
#include <vector>

class xml_node_base 
{
    public:
      virtual ~xml_node_base() = default;
      void output(std::ostream& os) const
      {
        do_output_open(os);
        do_output_body(os);
        do_output_close(os);
      }
    protected:
      virtual void do_output_open(std::ostream& os) const = 0; // abstract
      virtual void do_output_body(std::ostream&) const { } // not abstract
      virtual void do_output_close(std::ostream& os) const = 0; // abstract
};

using xml_node_base_t = std::shared_ptr<xml_node_base>;
using xml_node_bases_t = std::vector<xml_node_base_t>;

template <typename T, typename... Args>
inline xml_node_base_t make_xml_node(Args&&... args)
{
      return std::make_shared<T>(std::forward<Args>(args)...);
}   

class xml_node: virtual public xml_node_base
{
    private:
      std::string const& node_name;
    public:
      xml_node() = delete;
      xml_node(std::string const& name) : node_name(name)
      {
      };
    protected:
      void do_output_open(std::ostream& os) const override
      {
        os << "<" << node_name << ">";
      };
      void do_output_close(std::ostream& os) const override
      {
        os << "</" << node_name << ">";
      };
};

class xml_node_with_children: public xml_node

{
    private:
      xml_node_bases_t children_;
    public:
      xml_node_with_children() = delete;
      xml_node_with_children(std::string const& name) : xml_node(name)
      {
      };
      xml_node_with_children(std::string const& name, std::size_t reserve) : xml_node_with_children(name)
      {
        children_.reserve(reserve);
      };
      xml_node_with_children(std::string const& name, xml_node_bases_t children) : xml_node(name), children_(std::move(children))
      {
      };
    protected:
      auto& children() { return children_; };
      auto const& children() const { return children_; };
      void do_output_body(std::ostream& os) const
      {
        for (auto const& c : children_)
        {
            c -> output(os);
        }
      };
};

template <typename T>
class value_node : public xml_node
{
    private:
      T datum;
    protected:
      void do_output_body(std::ostream& os) const 
      {
        os << datum;
      }
    public:
      value_node(std::string const& name, T const& v) : xml_node(name), datum(v)
      {
      }
};

class note : public xml_node_with_children
{
    public:
      note() = delete;
      note(std::string const& to, std::string const& from, std::string const& subject, std::string const& message) : xml_node_with_children("note", 4)
      {
        children().push_back(make_xml_node<value_node<std::string>>("to",to));
        children().push_back(make_xml_node<value_node<std::string>>("from",from));
        children().push_back(make_xml_node<value_node<std::string>>("subject",subject));
        children().push_back(make_xml_node<value_node<std::string>>("message",message));
      }
};

class root : protected xml_node_with_children
{
    public:
      using xml_node_with_children::xml_node_with_children;
      using xml_node_with_children::output;
      using xml_node_with_children::children;
};

std::ostream& operator<<(std::ostream& os, root const& r)
{
    r.output(os);
    return os;
}

int main()
{
  root notes{"notes"};
  notes.children().push_back(
    make_xml_node<note>("Joe", "UPS", "Reminder", "Pick up your package!")
  );
  notes.children().push_back(
    make_xml_node<value_node<double>>("priority",54.23)
  );
  std::cout << notes << '\n';
}

Я думаю, что проблема может быть связана с циклом for в строке 90, так как я не очень хорошо знаком с оператором ->.

включение дезинфицирующего средства адресов может помочь вам в отладке: godbolt.org/z/6san37xq3

Alan Birtles 15.02.2023 12:49
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  std::string const& node_name;

      xml_node(std::string const& name) : node_name(name)

Этот член класса является ссылкой, и конструктор инициализирует его из ссылки, которая передается конструктору в качестве параметра.

Давайте проследим все в обратном порядке и посмотрим, откуда изначально берется параметр для конструктора. Вот один пример:

children().push_back(make_xml_node<value_node<std::string>>("to",to));

Параметр представляет собой литеральную строку, "to".

C++ очень известен и очень хорошо известен тем, что дает всем возможность выстрелить себе в ногу, если это то, что они действительно хотят сделать, поэтому:

  1. Создается временный объект std::string.

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

  3. Ссылка на этот объект сохраняется в члене базового класса.

  4. После завершения всех конструкторов и завершения выполнения этого оператора временный std::string объект, которому принадлежит этот "to", уничтожается.

  5. Экземпляр класса теперь имеет ссылку на уничтоженный объект в своем node_name.

  6. Это повторяется для всех других объектов в показанном коде, построенных таким образом.

  7. Ты только что выстрелил себе в ногу.

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