Search code examples
c++initializer-list

c++ initializer list for custom classes working abnormally


Can anyone please help me understand what is wrong with the below code?

I am using C++20

I am initializing the vector of vector of class 'Interval', but it's getting initialized to 0s.

#include <bits/stdc++.h>
using namespace std;

class Interval {
public:
    int start;
    int end;

    Interval() {}

    Interval(int _start, int _end) {
        start = _start;
        end = _end;
    }
};

vector<Interval> solve(vector<vector<Interval>> schedule) {
    vector<Interval> allSchedule;

    for(auto it : schedule) {
        for(auto it1 : it) {
            allSchedule.push_back(it1);
        }
    }

    auto comparator = [](Interval a, Interval b) {
        return a.start > b.start;
    };
    sort(allSchedule.begin(), allSchedule.end(), comparator);

    return allSchedule;
}

int main() {
    vector<vector<Interval>> schedule;
    schedule.push_back({new Interval(1,2), new Interval(5,6)});
    schedule.push_back({new Interval(1,3), new Interval(4,10)});
    vector<Interval> allSchedules = solve(schedule);
    for(auto it : allSchedules) {
        cout << it.start << " -> " << it.end << endl;
    }
    return 0;
}

Getting the below output ( Unexpected )

1 -> 2
1 -> 3
0 -> 0
0 -> 0

Solution

  • vector<vector<Interval>> schedule;
    schedule.push_back({new Interval(1,2), new Interval(5,6)});
    

    that's a very weird bug, because vector has a constructor that can be used to initialize it from two pointers (iterators) to other container, for example:

    Interval intervals[2];
    vector<vector<Interval>> schedule;
    schedule.push_back(std::vector<Interval>{ &(intervals[0]), &(intervals[2])});
    

    but for this to work correctly, you need both pointers to point to the start and end of an array, in your case both pointers returned by operator new don't point to the same container, so this is undefined behavior, and address santizer marks this as buffer overflow.

    with that said, you shouldn't be using operator new to create objects when aggregate initializing the vector, so the correct syntax is as follows.

    vector<vector<Interval>> schedule;
    schedule.push_back({Interval(1,2), Interval(5,6)});
    schedule.push_back({Interval(1,3), Interval(4,10)});