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

Автор ofi, история, 7 лет назад, По-английски
vector<int> v;

int f()
{
	v.push_back(-1);
	return 1;
}
int main()
{
	v.push_back(0);
	cout<<v[0]<<endl;
	v[0]=f();
	cout<<v[0]<<' '<<v[1]<<endl;
		
	return 0;
}

expected output:

0

1 -1

output:

0

0 1

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

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

When evaluating v[0]=f(); vector resizes from 1 to 2, reallocation happens, but the left-hand side address is evaluated before reallocation happens, so you perform an assignment to the memory region that is not a content of a vector any more.

The order of evaluation of sides in an assignment operator is not defined, thus you have UB.

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

    This paper "Refining Expression Evaluation Order for Idiomatic C++" was proposed for the C++17 standard. Pretty sure that it also did get accepted, so it shouldn't be UB anymore. Though I didn't find any proof other than g++ -std=c++17 doing the expected thing.

    Btw, pretty funny that you are allowed to write C++ proposals in Word...

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

      To get proof open the latest working draft based on c++17 branch n4659 and check if the changes from proposal are there. [Cppreference]http://en.cppreference.com/w/cpp/language/eval_order) is also a good source.

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

        Yeah, should have checked it yesterday, but I was too tired.

        Just for reference, the C++17 draft says: "The right operand is sequenced before the left operand." (under 8.18 Assignment and compound assignment operators)

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

      Personally, I see no harm if it is written in Word, as long as the idea is clearly expressed :)

»
7 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

The following modification produces the expected output.

int w = f(); v[0] = w;

Global variables should be used carefully so as to avoid such unexpected side effects.

Best wishes

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

Thanks, it really was usefull.