26

My ideas were quite simple. I wish to copy element by element from vector temp to vector data.

void copy(vector<int> &data, vector<int> &temp)
{    
    int i=0;
    while (i<data.size()) {
    data[i]=temp[i++];//unsequenced modification and access to "i"
    cout<<i<<endl;
}

Outputs: temp={1,2,3,4} but data={1,1,2,3} even if i's cout values are 1,2,3,4

wonder why. Thanks for help in advance!

Genie
  • 363
  • 1
  • 3
  • 5
  • 2
    You can do this with one of the insert overloads of the vector class. Don't reinvent. Your specific problem: don't increment and refer to i in one statement. That's undefined behaviour and the compiler might eat your cat. Also int is not the best choice for the type of i. – Bathsheba Nov 16 '15 at 19:43
  • I've voted to reopen since there are more problems aside from the UB. But if folk still think it should be closed, please go ahead. – Bathsheba Nov 16 '15 at 19:47
  • @Bathsheba What other issues? The typo of missing a closing curly brace? – NathanOliver Nov 16 '15 at 19:49
  • There's a const missing in the prototype, and int is not a good type for I. – Bathsheba Nov 16 '15 at 19:50

3 Answers3

30

The line

data[i]=temp[i++];//unsequenced modification and access to "i"

has unspeified behavior. The result of executing the line will be different depending on whether data[i] is evaluated first or temp[i++] is evaluated first. More dangerously, it will result in undefined behavior if temp[i++] is evaluated first for the last element of the vector.

Use

while (i<data.size()) {
    data[i]=temp[i];
    ++i;
}

As an alternative, use the std::copy function.

void copy(vector<int> &data, vector<int> &temp)
{
   std::copy(temp.begin(), temp.end(), data.begin());
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 3
    And change the type, and the function prototype, then use the standard library function. – Bathsheba Nov 16 '15 at 19:49
  • 1
    Undefined behaviour means anything can happen; your second sentence is more like a description of unspecified behaviour – M.M Nov 03 '18 at 12:25
-1

One might wonder why the behavior in a case like this isn't defined to be equivalent to incrementing in a separate statement following the one in question. I imagine the reason is that processors have some ability to do post increment for you (see the lodsw family of instructions). When using those instructions, the post increment must occur at the time you fetch the data. So to guarantee the post increment followed all other uses of the incremented variable would require that that fetch be done last, or at least after all other uses of the rsi in that statement. The designers probably decided that was too constraining.

  • Oh, I see where I went wrong here now - I meant for this to be a comment to R Sahu's answer, not an answer to the OP. I'm interesting in improving my previous poorly received content - can I just delete this answer and repost it as a comment? I know the system tracks deletions too - any advice would be appreciated. – Kip Ingram Nov 02 '19 at 12:19
-3

Why people says about undefined behavior?

data[i]=temp[i++];

In this case, first, we will take value from temp[I] (example: y), then "i" will be incremented by 1 (i++), and after that, value from temp[i] (y in our case) will be stored in data[i], where "i" is already incremented by 1.

  • 2
    If that would be always the case and defined that way, then it would not be undefined behavior. Undefined behavior exists if the specs e.g. do not specify the order in which `data[i]` and `temp[i++]` have to be evaluated, so the index used could be the same for both vectors or could be off by one. And that could vary depending on the compiler, the settings or the code and is UB as of that. The specification might change that in future versions of c++, certain things that have been UB in c++11 are now well defined in c++17 and newer. – t.niese Nov 03 '18 at 12:13
  • @t.niese undefined behaviour means anything can happen; the possibilities are not limited to the cases you list – M.M Nov 03 '18 at 12:24
  • - «if the specs e.g. do not specify the order in which data[i] and temp[i++] have to be evaluated, so the index used could be the same for both vectors or could be off by one.» Hm, but this behavior is specified in specs as i know… As we know, operator = have right to left associativity. So, expression on the right side (temp[i++]) should be calculated first. «i++» means that first, value of I should be used in expression, and at the end, i will be increased by 1. This behavior also in specs. – GavriiL Nov 03 '18 at 14:09
  • So, we calculated temp[i], and var i was increased by one, it`s time, according right to left associativity, to set result of right expression to array: data[i]. This behavior is specified in spec… – GavriiL Nov 03 '18 at 14:09
  • 1
    @GavriiL "associativity of an operator" is not related to "evaluation order of operands". Right to left associativity of = means that A=B=C is equivalent(I'm not sure this is a proper word) to A=(B=C), not (A=B)=C. That's all. It does not guarantee the right operand(value of temp[i++]) shall be evaluated earlier than the left operand(location of data[i]). http://c-faq.com/expr/evalorder1.html – gypark Jan 10 '19 at 08:14