размер std :: vector со структурными элементами - PullRequest
1 голос
/ 31 октября 2010

У меня проблемы с получением правильного размера вектора с элементами структуры. Класс элемента определяется следующим образом (я не опускал никаких подробностей, хотя думаю, что единственный важный факт - это класс, содержащий int и два типа double):

class Interval
{
public:
    Interval(int _i = 0, scalar _l = 0, scalar _r = 0) :
        index(_i),
        l(_l),
        r(_r)
    { }

    inline double left(void)    const { return l; }
    inline double right(void)   const { return r; }

    inline bool operator < (const Interval & i2) const { return left() < i2.left(); }

public:
    int index;
    double l;
    double r;

};

Тогда в функции у меня есть этот код:

std::vector<Interval> arr(10);
int s1 = arr.size();
int s2 = arr.end() - arr.begin();

Значение s1, которое я получаю, равно 15, а s2 - правильное значение 10. Что происходит? Разве size () не должен возвращать точное количество элементов? Разве он не должен совпадать с arr.end () - arr.begin ()?

Любой ответ и комментарий приветствуется.

Ответы [ 4 ]

1 голос
/ 31 октября 2010

Работает как положено в Кодовая панель

1 голос
/ 31 октября 2010

Во-первых, прекратите использование тегов HTML при форматировании кода.Вместо этого используйте кнопку [Код].

Во-вторых, то, что вы описываете, является загадкой, которая не поддается никакому объяснению.Вы должны получить одинаковое значение - 10 - в s1 и s2.Это если вам каким-то образом не удалось разрушить целостность вашего вектора в каком-то другом коде (т.е. код, который вы запускаете, не является кодом, который вы нам показываете).

0 голосов
/ 31 октября 2010

Обновление: после изучения кодовой базы в проекте я обнаружил другой класс с тем же именем «Interval» в другом заголовке, написанном другими людьми (я плохо выбрал такое простое слово, как имя моего класса). Этот класс содержит два типа double (16 байт на моем компьютере, в то время как мой класс имеет 24 байта), что, по-видимому, объясняет, почему вызов size () возвращает на 50% больше, чем фактическое количество элементов.

Но я не понимаю, как std :: vector может быть сбит с толку двумя определениями (я не включил этот заголовок в свой код, но мои заголовки, вероятно, включены в другие части проекта после включения этого заголовка ) и как end () - begin () использует одно определение, а size () использует другое определение.

Кстати, чтобы избежать таких коллизий в многопрограммном проекте, лучше всего использовать пространства имен, верно? Спасибо.

0 голосов
/ 31 октября 2010

Редактировать: Теперь, когда вы предоставили больше информации, возможно, мы сможем пролить свет на это запутанное поведение.

Вы нарушили Правило одного определения .Результаты этого на самом деле не определены, но мы можем сделать некоторые обоснованные предположения на основе ваших наблюдаемых результатов.

Функции шаблона всегда объявляются как встроенные, поскольку это требуется для подстановки параметров шаблона.Когда компилятор сталкивается с одной из этих функций, он может выбрать ее испускание в виде встроенного кода или создание тела функции и ее вызов.Если он создает тело функции, компоновщик становится ответственным за устранение дублирующихся определений в разных единицах перевода.Компоновщик не делает большой проверки, чтобы видеть, являются ли кажущиеся дубликаты функционально эквивалентными, он просто идет по оформленному имени функции, которое зависит от типов аргументов;если все типы имеют одинаковые имена, они предполагаются идентичными.Он может сделать это предположение из-за правила «Одно определение».

Таким образом, вы можете иметь определение класса, которое не включено в ваш источник, повлиять на исход вашего кода - компоновщик заменяет неверную копиюкод для хорошего.Если компилятор генерирует встроенный код, вы получите ожидаемый результат, если компоновщик подключится, у вас будет 50/50 шанс ошибиться.И даже если вашему коду повезло, какой-то другой фрагмент кода теперь поврежден.


Оригинальный ответ: вектор может быть больше запрашиваемого размера, но size не будет отражать это значение;Вы можете проверить это, используя capacity.Избыточное хранилище будет частью использования памяти, но элементы не будут инициализированы, и любая попытка доступа за пределами результата size приведет к неопределенному поведению.
...