0

I'm a beginner programmer looking to understand why my objects are being deleted, sometimes even twice. I'm trying to avoid creating them on the heap for this project as that is a more advance topic I will try at a later time.

Whats causing the book1, book2 etc.. objects to be instantly deleted? Also it outputs the same book object being deleted twice in a row sometimes for some reason? The same effect happens when using 'case 3: ' in the switch statement through the menu.

#include <iostream> #include <vector> using namespace std; class Book { public: // Constructor Prototype Book(string author = "Auth", string title = "Title", string publisher = "Pub", float price = 1.99, int stock = 1); // Destructor Prototype ~Book(); // Methods string get_title() const { return title; } private: string author; string title; string publisher; float price; int stock; }; // Constructor definition Book::Book(string author, string title, string publisher, float price, int stock) : author{author}, title{title}, publisher{publisher}, price{price}, stock{stock} { cout << "Book: " << title << " was created." << endl; } // Destructor definition Book::~Book() { cout << "Book: " << title << " has been destroyed." << endl; } // Functions void showMenu(); void getChoice(); void userChoice(int choice); void showBooks(vector<Book> bookList); // Global Vector vector<Book> bookList; int main() { // Creating Book objects for testing purposes Book book1("Marcel Proust", "In Search of Lost Time", "Pub", 14.99, 5); Book book2("James Joyce", "Ulysses", "Pub", 25.99, 4); Book book3("Miguel de Cervantes", "Don Quixote", "Pub", 35.99, 3); Book book4("Gabriel Garcia Marquez", "One Hundred Years of Solitude", "Pub", 100.99, 2); Book book5("F. Scott Fitzgerald", "The Great Gatsby", "Pub", 49.99, 1); // Pushing book1-5 into the vector of Book objects bookList.push_back(book1); bookList.push_back(book2); bookList.push_back(book3); bookList.push_back(book4); bookList.push_back(book5); while(true) { showMenu(); getChoice(); } return 0; } void showMenu() { cout << "\tMENU" << endl; cout << "1. Purchase Book" << endl; cout << "2. Search for Book" << endl; cout << "3. Show Books available" << endl; cout << "4. Add new Book" << endl; cout << "5. Edit details of Book" << endl; cout << "6. Exit" << endl; } void getChoice() { int choice; cout << "Enter your choice (1-6): "; cin >> choice; userChoice(choice); } void userChoice(int choice) { switch(choice) { case 1: cout << "Case 1 called." << endl; break; case 2: cout << "Case 2 called." << endl; break; case 3: cout << "Case 3 called." << endl; showBooks(bookList); break; case 4: cout << "Case 4 called." << endl; break; case 5: cout << "Case 5 called." << endl; break; case 6: cout << "Case 6 called." << endl; exit(0); } } void showBooks(vector<Book> bookList) { for (Book bk : bookList) { cout << "Book: " << bk.get_title() << endl; } } 

Edit:

Why does it delete the same object 2-3 times in a row sometimes? output (in this case it was "In Search of Lost Time"):

Book: In Search of Lost Time was created. Book: Ulysses was created. Book: Don Quixote was created. Book: One Hundred Years of Solitude was created. Book: The Great Gatsby was created. Book: In Search of Lost Time has been destroyed. Book: In Search of Lost Time has been destroyed. Book: Ulysses has been destroyed. Book: In Search of Lost Time has been destroyed. 
11
  • 2
    Because you're copying them like crazy and destroying copies. See Rule of Three. Commented Aug 15, 2022 at 1:51
  • 1
    Consider using emplace_back for directly creating books in place as new vector elements. Commented Aug 15, 2022 at 1:58
  • 1
    And if you do a lot of books, you may want to do a vector.reserve first, as when vector needs to reallocate it also has to do moves/copies, Commented Aug 15, 2022 at 2:00
  • 1
    bookList.emplace_back("Marcel Proust", "In Search of Lost Time", "Pub", 14.99, 5); instead of the push_back should save making a copy unless the compiler optimizer was good enough able to get rid of it on its own. Commented Aug 15, 2022 at 2:11
  • 1
    One more thing that i missed: Your showBooks should be taking booklist by const reference. Right now you are making an unneeded copy of the vector when you call showBooks. Here is a test modification Commented Aug 15, 2022 at 2:35

2 Answers 2

2

here

for (Book bk : bookList) 

you are making copies of Books. Do this instead

 for (Book &bk : bookList) 

now you just have a reference

Sign up to request clarification or add additional context in comments.

5 Comments

Got it, but before the menu is even called, it deletes an obj 2-3 times in a row sometimes thats what i don't get
@OP I am sure there are other cases, this one was simply spot (and fix)
@OP pushing the books into a vector copies too
@pm Roger that, I understand that now thanks!
@OP - use emplace_back
0

As per the various suggestions in the comments I have compiled the program to suit your needs. It will work without any unwanted allocations. Changes I made are: 1.Reserving the vector to 5 elements. 2. Emplacement. 3. Passing the vector as a reference to the function and 4. Taking the vector elements as a reference while iteration.

#include <iostream> #include <string> #include <vector> using namespace std; class Book { public: // Constructor Prototype Book(string author = "Auth", string title = "Title", string publisher = "Pub", float price = 1.99f, int stock = 1); // Destructor Prototype ~Book(); // Methods string get_title() const { return title; } private: string author; string title; string publisher; float price; int stock; }; // Constructor definition Book::Book(string author, string title, string publisher, float price, int stock) : author( author ), title( title ), publisher( publisher ), price( price ), stock( stock ) { cout << "Book: " << title << " was created." << endl; } // Destructor definition Book::~Book() { cout << "Book: " << title << " has been destroyed." << endl; } // Functions void showMenu(); void getChoice(); void userChoice(int choice); void showBooks(vector<Book>& bookList); // Global Vector vector<Book> bookList; int main() { bookList.reserve(5); bookList.emplace_back("Marcel Proust", "In Search of Lost Time", "Pub", 14.99f, 5); bookList.emplace_back("James Joyce", "Ulysses", "Pub", 25.99f, 4); bookList.emplace_back("Miguel de Cervantes", "Don Quixote", "Pub", 35.99f, 3); bookList.emplace_back("Gabriel Garcia Marquez", "One Hundred Years of Solitude", "Pub", 100.99f, 2); bookList.emplace_back("F. Scott Fitzgerald", "The Great Gatsby", "Pub", 49.99f, 1); while (true) { showMenu(); getChoice(); } return 0; } void showMenu() { cout << "\tMENU" << endl; cout << "1. Purchase Book" << endl; cout << "2. Search for Book" << endl; cout << "3. Show Books available" << endl; cout << "4. Add new Book" << endl; cout << "5. Edit details of Book" << endl; cout << "6. Exit" << endl; } void getChoice() { int choice; cout << "Enter your choice (1-6): "; cin >> choice; userChoice(choice); } void userChoice(int choice) { switch (choice) { case 1: cout << "Case 1 called." << endl; break; case 2: cout << "Case 2 called." << endl; break; case 3: cout << "Case 3 called." << endl; showBooks(bookList); break; case 4: cout << "Case 4 called." << endl; break; case 5: cout << "Case 5 called." << endl; break; case 6: cout << "Case 6 called." << endl; exit(0); } } void showBooks(vector<Book>& bookList) { for (const auto& book : bookList){ cout << "Book: " << book.get_title() << endl; } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.