Блог пользователя Logvinov_Leon

Автор Logvinov_Leon, 12 лет назад, По-русски

Сегодня я наткнулся на одну очень не приятную багу. Рассмотрим следующий код.

#include <iostream>
#include <map>
using namespace std;
int main(){
	map<int,int> m;
	m[0]=m.size();
	cout<<m[0]<<endl;
}

Как вы думаете, что выведет программа? Логично было бы 0. Ведь map изначально пуст. И Visual Studio 2008 express действительно выводит 0. Но вот если пользоваться g++ то на выходе окажется единица. Меня давно предупреждали в ЛКШ, что студия является компилятором неизвестного языка, но тут g++ повёл себя не адекватно. Если я правильно понимаю, то сначала должен вычисляться правый операнд оператора присвоить. Если я не прав, то объясните где. А если кто знает что-то подобное, то прошу поделиться опытом.

  • Проголосовать: нравится
  • +8
  • Проголосовать: не нравится

»
12 лет назад, # |
  Проголосовать: нравится +2 Проголосовать: не нравится

При обращении к элементу map через квадратные скобки, при его отсутствии, создается новый элемент map'a. Не знаю, как в MS C++, но в GNU это 100% так. На каком-то из недавних четвертьфиналов слетало много решений из-за неправильного обращения с map'ом. Чтобы обратиться к элементу map'a без риска создать новый элемент, нужно воспользоваться методом find().

»
12 лет назад, # |
  Проголосовать: нравится +30 Проголосовать: не нравится

Это Undefined Behaviour — не определен порядок вычисления. Можно почитать http://alenacpp.blogspot.ru/2005/11/sequence-points.html или http://en.cppreference.com/w/cpp/language/eval_order

Правильно написать или int id = m.size(); m[0] = id; или m.insert(pair<int, int>(0, m.size());

»
12 лет назад, # |
  Проголосовать: нравится +6 Проголосовать: не нравится

Я стану на сторону g++.

Оператор "равно" грубо говоря принимает две ссылки: одну на то куда присваиваем, другую на то что присваиваем. Вы считаете логичным вычислять аргументы функции в обратном порядке? :)

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится +10 Проголосовать: не нравится

    Если бы порядок вычисления вообще был бы определен, то вычислять в обратном порядке было бы как раз логичнее: http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится +7 Проголосовать: не нравится

      Это соглашение определяет в каком порядке класть аргументы в стек. Однако языки высокого уровня созданы как раз для того чтобы мы не клали руками в стек параметры, а код был читабельный и понимабельный. С человеческой точки зрения вычислять наоборот — странно :)

      • »
        »
        »
        »
        12 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Если бы руками клали в стек, то вероятно в этом порядке же и вычисляли. А вообще если результат выполнения кода зависит от того, в каком порядке будут вычисляться аргументы вызываемой функций, то вероятно он уже не совсем читабельный и не совсем понимабельный =).

      • »
        »
        »
        »
        12 лет назад, # ^ |
          Проголосовать: нравится -6 Проголосовать: не нравится

        Ну вот как раз с человеческой точки зрения обратный порядок даже более правильно, если у нас например есть a=b=c=d=e, то намного проще было бы вычислять с конца — на каждом шаге вычисления мне не нужно помнить что там где произошло, я просто иду с конца и на каждом шаге помню всего три значения: левый операнд, правый операнд, значение присвоения; а при прямом порядке я должен запомнить результат выполнения на каждом шаге. Это конечно всё надумано и такие длинные равно признак гавнокодерства, речь лишь о том что проще для восприятия.

        • »
          »
          »
          »
          »
          12 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          Зря я начал этот тред, обсуждаем как правильнее говнокодить :)

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      А вообще, очевидно, что behaviour undefined и писать на олимпиадах такое — себе дороже.