-5

I have the class Flashcard declared in Flashcard.h and Flashcard.cpp. I want to make a class CardList which should store a std::vector<Flashcard> as well as some other information, and provide some methods for manipulating it.

CardList.h

#include <vector>
#ifndef LC_FLASHCARD
    #include "Flashcard.h"
#endif

class CardList
{
    public:
        /* Constructor */
        CardList (int number_of_cards = 1);
        /* Returns the j'th card. */
        Flashcard getCard ( int j );
        /* Replaces the j'th card with new_card. */
        void setCard ( int j, Flashcard new_card );
        /* ... */

    private:
        std::vector<Flashcard> card_list;
        /* ... */
};

CardList.cpp

#include "CardList.h"

CardList::CardList ( int number_of_cards ) {
    std::vector<Flashcard> card_list(number_of_cards);
}

CardList::~CardList ( void ) { }

Flashcard CardList::getCard ( int j ) {
    return this->card_list[j];
}

void CardList::setCard ( int j, Flashcard new_card ) {
    this->card_list[j] = new_card;
}

Flashcard CardList::drawCard ( void ) {
    return this->getCard(0);
}

The problem

Whenever I call CardList::getCard or CardList::setCard, I get a segfault. For example:

#include "Flashcard.h"
#include "CardList.h"
/* ... */

int main( int argc, char** argv ) {
    /* Creates flashcard card */
    Flashcard card;
    /* (do things to card) */ 

    CardList card_list(7);
    std::cout << "Declaration and initialisation of card_list successful" << std::endl;

    card_list.setCard(0, card); // *** SEGFAULT ***
    std::cout << "Assignment successful" << std::endl;

    /* ... */
    return 0;
}

I think the problem is with my constructor CardList::CardList, but how do I fix it?

  • 1
    I'd suspect your error appears in the copy constructor, or destructor of `Flashcard`, which you deny to let us see it. I'd recommend to use the debugger, step through your code, and identify where it comes from. – πάντα ῥεῖ Aug 18 '15 at 15:38

2 Answers2

1

This code does not do at all what you think:

CardList::CardList ( int number_of_cards ) {
    std::vector<Flashcard> card_list(number_of_cards);
}

What you should do is:

CardList::CardList ( int number_of_cards ) :
    card_list(number_of_cards)
{
}

Your seg fault is because you never sized card_list. The code in your version of the constructor created a different temporary card_list that was destroyed as soon as the constructor exited. Meanwhile the card_list member was default constructed with a size of zero.

JSF
  • 5,281
  • 1
  • 13
  • 20
  • Thanks, that works. Is the `:` an example of http://stackoverflow.com/questions/1711990/what-is-this-weird-colon-member-syntax-in-the-constructor? – Jonathan Michael Foonlan Tsang Aug 18 '15 at 16:05
  • Yes, that `:` and the reasons it is often better than assignment within the body of the constructor seem to be explained well in that question you linked. – JSF Aug 18 '15 at 18:04
0

You have a property named card_list in your class but you don't do the initialization properly in your constructor. In your codes, you have:

CardList::CardList ( int number_of_cards ) {
    std::vector<Flashcard> card_list(number_of_cards);
}

In this case you are initializing a local variable named card_list instead of the class' property card_list.

The correct way to do it is as below:

CardList::CardList ( int number_of_cards ) {
    this->card_list = std::vector<Flashcard>(number_of_cards);
} 
dariush
  • 3,191
  • 3
  • 24
  • 43