-1

i am trying to create a 2d array holding pointers of my class. first, i'd like to assign all of them NULL:

Timetable::Timetable(int hours) : TimetableBase(hours){
    scheduledLectures = new Lecture**[5];
    for (int i = 0; i < 5; i++) {
        scheduledLectures[i] = new Lecture*[hours];
        for (int j = 0; j < hours; j++)
            scheduledLectures[i][j] = NULL;
    };
}

this is for a timetable generator application. i have a function to set these pointers to a specific object.

void Timetable::setLecture(Lecture& lecture){
    while ((lecture.getDuration()) -1 > 0){
        scheduledLectures[lecture.getDayScheduled()][(lecture.getHourScheduled())+1] = &lecture;
    }
}

the compiler returns no errors for this, but when its running, it seems that the pointers remain NULLs. i am sure the error is inside the setter function (and almost sure that its a grammar mistake) but i cannot find the solution for that. whats wrong in here?

thank you

1 Answers1

0

Use a vector (or std::array) of pointers or shared_ptrs (or unique_ptrs depending on how your lifetimes are arranged) instead of a 2D array of pointers that you manage yourself. Save yourself the trouble of managing the memory and lifetimes of your objects manually.

class TimeTable {
    vector<vector<shared_ptr<Lecture>>> scheduledLectures;
};

Timetable::Timetable(int hours) 
        : TimetableBase(hours), 
        scheduledLectures(5, vector<shared_ptr<Lecture>>(5)) {}

void Timetable::setLecture(std::shared_ptr<Lecture> lecture){
    while ((lecture->getDuration()) -1 > 0) { // not sure what this does
        scheduledLectures[lecture->getDayScheduled()][(lecture->getHourScheduled())+1] = lecture;
    }
}

You can test whether a shared_ptr is null like follows

auto s_ptr = std::shared_ptr<int>{}; // null
// either assign it to a value or keep it null
if (s_ptr) { 
    // not null
}

If you are managing the memory of the Lecture objects elsewhere then just use a 2D vector of pointers and trust your code

class TimeTable {
    vector<vector<Lecture*>> scheduledLectures;
};

Timetable::Timetable(int hours) 
        : TimetableBase(hours), 
        scheduledLectures(5, vector<Lecture*>(5)) {}

void Timetable::setLecture(Lecture& lecture){
    while ((lecture.getDuration()) -1 > 0) { // not sure what this does
        scheduledLectures[lecture.getDayScheduled()][(lecture.getHourScheduled())+1] = &lecture;
    }
}
Curious
  • 20,870
  • 8
  • 61
  • 146
  • please don't use vector of vectors as a 2d array. It's not hard to make a flat 2d array class. – Sopel May 14 '17 at 21:30
  • @Sopel no, its not overkill to use a `vector` to abstract away managing memory for a flat 2d array. If you think so, then use an `std::array` – Curious May 14 '17 at 21:32
  • 1. Vector of vectors has unnecesary overhead of more allocations (also possibly worse locality) 2. It is not obvious that the code doesnt use it as a jagged array. 3. You dont need the dynamic part of the vectlr – Sopel May 14 '17 at 22:17
  • @Sopel Overhead in terms of what? Such claims are only be justified if there is a dire requirement for minimizing allocations at all costs. Vector allocation are O(1) amortized, because vectors double when they need to reallocate memory, so the cost is not that much over a large sequence of insertions. When you talk about fewer elements, its not that much at all because well there are fewer allocations. If you absolutely cannot have allocations, then an `std::array` works well. – Curious May 14 '17 at 22:21
  • Regarding 2, you can use vectors even when you dont need jagged arrays. Regarding 3, then use an `std::array`, the user using `new` indicates that the `5` is not set in stone. OP's code is dynamically allocating memory, and the number of allocations when switching to a vector implementation are likely exactly the same – Curious May 14 '17 at 22:24
  • You cant use std array in this case – Sopel May 14 '17 at 22:26
  • @Sopel Why not? – Curious May 14 '17 at 22:27
  • Because the size of it has to be known at compile time – Sopel May 14 '17 at 22:28
  • Also you can compare smart poiners with nullptr_t directly – Sopel May 14 '17 at 22:29
  • @Sopel that was in response to you saying `3. You dont need the dynamic part of the vector` The need for dynamic allocations is why I suggested using a vector in the first place. If you are suggesting variable length arrays then take a look at http://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard – Curious May 14 '17 at 22:29
  • Im not suggesting vlas – Sopel May 14 '17 at 22:30
  • @Sopel Comparing a pointer to `nullptr` explicitly is seen as bad style by a lot of people (myself included) as opposed to just `if (ptr)` or `if (!ptr)`, then what were you suggesting as a justification for not using `std::vector` when you said `You dont need the dynamic part of the vector`? – Curious May 14 '17 at 22:31
  • @Sopel Also see http://stackoverflow.com/questions/381621/using-arrays-or-stdvectors-in-c-whats-the-performance-gap – Curious May 14 '17 at 22:36
  • if I use a vector for this, how can I call the setLecture function? before that I was calling it with a reference to a lecture object. now it seems like i have to convert this pointer somehow – Tibor Alács May 15 '17 at 08:07