2010-10-31 4 views
1

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

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. Что происходит? Разве размер() не должен точно возвращать количество элементов? Разве это не должно быть таким же, как arr.end() - arr.begin()?

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

+0

Нет никакого способа узнать, что это сделает рабочая реализация вектора. Пожалуйста, покажите весь код, который вы используете, чтобы проверить это. –

+0

Да, размер() должен равняться концу() - begin(); нам нужен лучший тестовый пример, чтобы понять, что происходит. – 2010-10-31 04:17:42

+0

Не расплывчатый, будь тузом; научись писать правильный тестовый файл! http://sscce.org/ http://www.xs4all.nl/~weegen/eelis/iso-c++/testcase.xhtml http://tinyurl.com/so-hints – 2010-10-31 04:18:22

ответ

0

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

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

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

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


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

+0

Спасибо, я понимаю разницу между емкостью и размером. У меня проблемы с размером. – fang

+0

Большое спасибо. Теперь это ясно. – fang

+0

Я изо всех сил пытаюсь понять, как код OP нарушает ODR, или как этот ответ решает проблему. –

1

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

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

+0

Спасибо за подсказку. В следующий раз я постараюсь сделать это правильно. – fang

+0

Я знаю, что я показал, не имеет никакого смысла. То, о чем я прошу, - это, по сути, некоторое понимание того, что может быть, возможно, запутаться. Вторая половина показанного кода инициализирует вектор и сразу же запрашивает размер, поэтому возможностей, которые я могу себе представить, мало. Мне нужен опыт экспертов, чтобы знать подходящее место для просмотра (например, вы видели похожие проблемы раньше с другими людьми, каковы были ответы и т. Д.). Я уверен, что окончательный ответ на этот вопрос, скорее всего, глупый, но я застрял на себе. – fang

1

Работы, как ожидается, в Codepad

+0

Спасибо за проверку. Я тоже это сделал, и, как и ожидалось, проблема не в той части кода, которую я показал. Как я уже сказал в последнем комментарии, я ищу ответы, например, какой механизм на C++ может позволить другому коду вмешиваться в код так же просто, как те, что я показал, потому что я не могу придумать ни одного. – fang

0

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

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

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

+0

Спасибо за дополнительную информацию, я обновил свой ответ. –

+0

Теперь задайте вопрос, но вы могли бы только что отредактировать свой вопрос. –

+0

@Marcelo, справа, спасибо за подсказку. Я видел, как пару человек отправляли обновления через ответы на свои вопросы раньше, поэтому я подумал, что это общий способ сделать это. Я никогда не понимал, что могу отредактировать оригинальный пост. – fang

 Смежные вопросы

  • Нет связанных вопросов^_^