Разный адрес в памяти при передаче по ссылке

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

У меня MainMenu вызывает SongMenu и уже когда я попадаю в SongMenu там другой адрес переменной, хотя должен быть как в MainMenu.И получается что данные не сохраняются. Пробовал делать через указатели, но там еще хуже.

MainMenu

SongMenu

MainMenu.h

#ifndef CONCERT_MAINMENU_H
#define CONCERT_MAINMENU_H


#include <cctype>
#include <regex>
#include "Menu.h"

class MainMenu : public Menu {
private:

    ConcertVotingSystem votingSystem;
    ConcertProgram program;
    std::unordered_map<std::basic_string<char>, int> votes;
    std::vector<Song> availableSongs;

    void votesForSongs();
    void createProgram();
    void toSummarize();

public:
    // Constructor
    MainMenu(ConcertVotingSystem &votingSystem,  ConcertProgram &program, std::unordered_map<std::basic_string<char>, int> &votes,
             std::vector<Song> &availableSongs) : Menu({
        "Song menu",
        "Allow users to vote for their favorite songs",
        "Create a concert program based on the most popular songs",
        "Display the concert program",
        "Print a message indicating that voting has passed",
        "Exit"
    }) {
        this->votingSystem = votingSystem;
        this->program = program;
        this->votes = votes;
        this->availableSongs = availableSongs;
    }

    // Method to handle menu selection
    void select(int selected) override;
};

#endif //CONCERT_MAINMENU_H

SongMenu.h

#ifndef CONCERT_SONGMENU_H
#define CONCERT_SONGMENU_H

#include <conio.h>
#include <limits>
#include "Menu.h"
#include "MainMenu.h"

class MainMenu;
class SongMenu : public Menu {
    ConcertVotingSystem votingSystem;
    ConcertProgram program;
    std::unordered_map<std::basic_string<char>, int> votes;
    std::vector<Song> availableSongs;

    void addSong();
    void updateSong();
    void deleteSong();
    void select(int selected) override;
public:
    SongMenu(ConcertVotingSystem &votingSystem,  ConcertProgram &program, std::unordered_map<std::basic_string<char>, int> &votes,
             std::vector<Song> &availableSongs) : Menu({
                              "Add song",
                              "Update song",
                              "Delete song",
                              "Back"
                      }) {
        this->votingSystem = votingSystem;
        this->program = program;
        this->votes = votes;
        this->availableSongs = availableSongs;

    }



};


#endif //CONCERT_SONGMENU_H

Реализация

MainMenu.cpp

#include <conio.h>
#include <limits>
#include "MainMenu.h"
#include "SongMenu.h"

#define NDEBUG


void MainMenu::select(int selected) {
    std::cout << "Selected: " << this->getOptions().at(selected) << std::endl;

    switch (selected) {
        case 0: // "Add some songs and artists to the system"
            system("cls");
            SongMenu(votingSystem, program, votes, availableSongs).run();
            _getch(); // Wait for the user to press a key
            system("cls");
            this->run();
            break;
        case 1: // Allow users to vote for their favorite songs
            votingSystem.displaySongs();
            votesForSongs();
            _getch();
            system("cls");
            this->run();
            break;
        case 2: // Create a concert program based on the most popular songs
            createProgram();
            _getch();
            system("cls");
            this->run();
            break;
        case 3: // Display the concert program


#ifdef NDEBUG
            printf("program : %p\n", (void*)&program);
            printf("voting system : %p\n", (void*)&votingSystem);
#endif
            program.display();
            _getch();
            system("cls");
            this->run();
            break;
        case 4: // Print a message indicating that voting has passed
            toSummarize();
            _getch();
            system("cls");
            this->run();
            break;
        case 5:
            exit(0);

    }
}




void MainMenu::votesForSongs() {
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');



    bool allWhitespace = true;
    std::string songName;
    do {
        std::cout << "\nEnter song: ";

        std::getline(std::cin, songName);

        for (char c: songName) {
            if (!std::isspace(c)) {
                allWhitespace = false;
                break;
            }
        }

        if (allWhitespace)
            std::cout << "Invalid input; please re-enter." << std::endl;


    } while (allWhitespace);

#ifdef NDEBUG
    printf("program : %p\n", (void*)&program);
    printf("voting system : %p\n", (void*)&votingSystem);
#endif
    votingSystem.voteForSong(songName);
}

void MainMenu::createProgram() {
  try {
      availableSongs = votingSystem.getAvailableSongs();
      if (availableSongs.empty()) return;
      // Check if there are any votes
      votes = votingSystem.getVotes();
      if (votes.empty()) return;
      std::sort(availableSongs.begin(), availableSongs.end(), [&](const Song& song1, const Song& song2) {
          return votes[song1.getTitle()] > votes[song2.getTitle()];
      });

      auto it = availableSongs.begin();
      for (int i = 0; i < availableSongs.size(); i++) {  // Include the top 3 songs in the program
          program.addSong(*it);  // Dereference the iterator to get the song
          ++it;  // Move the iterator to the next song
      }
  } catch (...) {
      system("cls");
      std::cout << "Something went wrong..."  << std::flush << std::endl;
      this->run();
  }
}

void MainMenu::toSummarize() {

#ifdef NDEBUG
    printf("program : %p\n", (void*)&program);
    printf("voting system : %p\n", (void*)&votingSystem);
#endif
    std::cout << "\n\nVoting has passed\n\n" << std::endl;
    // Iterate through the votes unordered_map and print out each song
    // title and the number of votes it received
    for (auto i = votes.begin(); i != votes.end(); ++i) {
        std::cout << i->first << ' ' << i->second << std::endl;
    }
}

SongMenu.cpp

#include "SongMenu.h"

#define NDEBUG

void SongMenu::select(int selected) {
    std::cout << "Selected: " << this->getOptions().at(selected) << std::endl;

    switch (selected) {
        case 0: // Add song


#ifdef NDEBUG
            printf("program : %p\n", (void*)&program);
            printf("voting system : %p\n", (void*)&votingSystem);
#endif
            votingSystem.displaySongs();
            addSong();
            _getch(); // Wait for the user to press a key
            system("cls");
            this->run();
            break;
        case 1: // Update song


#ifdef NDEBUG
            printf("program : %p\n", (void*)&program);
            printf("voting system : %p\n", (void*)&votingSystem);
#endif
            votingSystem.displaySongs();
            updateSong();
            _getch();
            system("cls");
            this->run();
            break;
        case 2: // Delete song


#ifdef NDEBUG
            printf("program : %p\n", (void*)&program);
            printf("voting system : %p\n", (void*)&votingSystem);
#endif
            votingSystem.displaySongs();
            deleteSong();
            _getch(); // Wait for the user to press a key
            system("cls");
            this->run();
            break;
        case 3:
            return;



    }
}


void SongMenu::addSong() {
    // Clear the input stream and ignore any leftover characters
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Initialize variables to store user input
    bool allWhitespace = true; // Flag to check if the string only contains whitespace characters
    bool isValid = false; // Flag to check if the input is valid
    // Prompt the user for the song name and validate the input
    std::string songName;
    do {
        std::cout << "\nEnter song: ";

        std::getline(std::cin, songName);
        // Check if the string only contains whitespace characters
        for (char c: songName) {
            if (!std::isspace(c)) {
                allWhitespace = false;
                break;
            }
        }
        // If the string only contains whitespace characters, prompt the user to re-enter
        if (allWhitespace)
            std::cout << "Invalid input; please re-enter." << std::endl;


    } while (allWhitespace);


    std::string artistName;
    allWhitespace = true;  // Reset the flag
    do {
        // Prompt the user for the artist name and validate the input
        std::cout << "\nEnter artist: ";
        std::getline(std::cin, artistName);
        // Check if the string only contains whitespace characters
        for (char c: artistName) {
            if (!std::isspace(c)) {
                allWhitespace = false;
                break;
            }
        }
        // If the string only contains whitespace characters, prompt the user to re-enter
        if (allWhitespace)
            std::cout << "Invalid input; please re-enter." << std::endl;


    } while (allWhitespace);

    int duration;
    do { // Prompt the user for the duration of the song and validate the input
        std::cout << "Enter duration of song in seconds: " << std::flush;
        std::cin >> duration;
        if (std::cin.good()) {
            //everything went well, we'll get out of the loop and return the value
            isValid = true;
        } else {
            //something went wrong, we reset the buffer's state to good
            std::cin.clear();
            //and empty it
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "Invalid input; please re-enter." << std::endl;
        }
    } while (!isValid);


#ifdef NDEBUG
    printf("program : %p\n", (void*)&program);
    printf("voting system : %p\n", (void*)&votingSystem);
#endif

    Song song(songName, artistName, duration);
    Artist artist(artistName, {song});
    votingSystem.addSong(song);
    votingSystem.addArtist(artist);
}

void SongMenu::deleteSong() {

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    bool allWhitespace = true; // Flag to check if the string only contains whitespace characters
    // Prompt the user for the song name and validate the input
    std::string songName;
    do {
        std::cout << "\nEnter song: ";

        std::getline(std::cin, songName);
        // Check if the string only contains whitespace characters
        for (char c: songName) {
            if (!std::isspace(c)) {
                allWhitespace = false;
                break;
            }
        }
        // If the string only contains whitespace characters, prompt the user to re-enter
        if (allWhitespace)
            std::cout << "Invalid input; please re-enter." << std::endl;


    } while (allWhitespace);


#ifdef NDEBUG
    printf("program : %p\n", (void*)&program);
    printf("voting system : %p\n", (void*)&votingSystem);
#endif
    votingSystem.deleteSong(songName);
}

void SongMenu::updateSong() {
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    // Update the song's title, artist, and duration
    bool allWhitespace = true; // Flag to check if the string only contains whitespace characters
    // Prompt the user for the song name and validate the input
    std::string oldTitle;
    do {
        std::cout << "\nEnter old song title: ";

        std::getline(std::cin, oldTitle);
        // Check if the string only contains whitespace characters
        for (char c: oldTitle) {
            if (!std::isspace(c)) {
                allWhitespace = false;
                break;
            }
        }
        // If the string only contains whitespace characters, prompt the user to re-enter
        if (allWhitespace)
            std::cout << "Invalid input; please re-enter." << std::endl;


    } while (allWhitespace);

    allWhitespace = true; // Flag to check if the string only contains whitespace characters
    // Prompt the user for the song name and validate the input
    std::string newTitle;
    do {
        std::cout << "\nEnter new song title: ";

        std::getline(std::cin, newTitle);
        // Check if the string only contains whitespace characters
        for (char c: newTitle) {
            if (!std::isspace(c)) {
                allWhitespace = false;
                break;
            }
        }
        // If the string only contains whitespace characters, prompt the user to re-enter
        if (allWhitespace)
            std::cout << "Invalid input; please re-enter." << std::endl;


    } while (allWhitespace);

    allWhitespace = true; // Flag to check if the string only contains whitespace characters
    // Prompt the user for the song name and validate the input
    std::string newArtist;
    do {
        std::cout << "\nEnter new artist: ";

        std::getline(std::cin, newArtist);
        // Check if the string only contains whitespace characters
        for (char c: newArtist) {
            if (!std::isspace(c)) {
                allWhitespace = false;
                break;
            }
        }
        // If the string only contains whitespace characters, prompt the user to re-enter
        if (allWhitespace)
            std::cout << "Invalid input; please re-enter." << std::endl;


    } while (allWhitespace);

    bool isValid = false;
    int newDuration;
    do { // Prompt the user for the duration of the song and validate the input
        std::cout << "Enter duration of song in seconds: " << std::flush;
        std::cin >> newDuration;
        if (std::cin.good()) {
            //everything went well, we'll get out of the loop and return the value
            isValid = true;
        } else {
            //something went wrong, we reset the buffer's state to good
            std::cin.clear();
            //and empty it
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "Invalid input; please re-enter." << std::endl;
        }
    } while (!isValid);


#ifdef NDEBUG
    printf("program : %p\n", (void*)&program);
    printf("voting system : %p\n", (void*)&votingSystem);
#endif

    votingSystem.updateSong(oldTitle, newTitle, newArtist, newDuration);
}

Ответы (1 шт):

Автор решения: Harry

У вас выполняется копирование переданных аргументов в локальные переменные:

    this->votingSystem = votingSystem;
    this->program = program;

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

Вот вам кратенький ("минимальный" :)) пример, который все должен прояснить:

class Ref
{
    int &p;
public:
    Ref(int&p):p(p){}
    void out() { cout << (void*)&p << endl; }
};

class Val
{
    int p;
public:
    Val(int&p):p(p){}
    void out() { cout << (void*)&p << endl; }
};


int main(int argc, char * argv[])
{
    int x = 5;
    cout << (void*)&x << endl;
    Ref r(x);
    Val v(x);
    r.out();
    v.out();
}
→ Ссылка