2016-06-09 2 views
0

Я наткнулся на эту проблему, работая над небольшим проектом.C++ наиболее неприятный векторный свод кода

#include <iostream> 
#include <string> 
#include <vector> 

int main() 
{ 
    std::vector<int*> v; 
    for (int x = 1; x < 6; ++x) 
    { 
     int * a = new int(x); 
     v.push_back(a); 
    } 

    unsigned int y = 4; 
    for (auto a : v) 
    { 
     std::cout << "BEFORE SWAP: v[0] = " << *v[0] << ", v[1] = " << *v[1] << ", v[2] = " << *v[2] << ", v[3] = " << *v[3] << ", v[4] = " << *v[4] << std::endl; 
     std::swap(a, v[y]); 
     std::cout << "AFTER SWAP: v[0] = " << *v[0] << ", v[1] = " << *v[1] << ", v[2] = " << *v[2] << ", v[3] = " << *v[3] << ", v[4] = " << *v[4] << std::endl; 
     std::cout << "==========" << std::endl; 
     --y; 
    } 

    // for (std::vector<int*>::iterator it = v.begin(); it != v.end(); ++it) 
    // { 
    //  std::cout << "BEFORE SWAP: v[0] = " << *v[0] << ", v[1] = " << *v[1] << ", v[2] = " << *v[2] << ", v[3] = " << *v[3] << ", v[4] = " << *v[4] << std::endl; 
    //  std::swap(*it, v[y]); 
    //  std::cout << "AFTER SWAP: v[0] = " << *v[0] << ", v[1] = " << *v[1] << ", v[2] = " << *v[2] << ", v[3] = " << *v[3] << ", v[4] = " << *v[4] << std::endl; 
    //  std::cout << "==========" << std::endl; 
    //  --y; 
    // } 

    // inb4 "You forgot to deallocate!" This is an example. 
} 

В конце кода есть две петли, которые выполняют ту же задачу, но по-другому.

для цикла с auto ключевого слова производит этот результат с пропущенными числами:

BEFORE SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 5 
AFTER SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 1 
========== 
BEFORE SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 1 
AFTER SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1 
========== 
BEFORE SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1 
AFTER SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1 
========== 
BEFORE SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1 
AFTER SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1 
========== 
BEFORE SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1 
AFTER SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1 
========== 

для цикла с итератор работает, как ожидалось:

BEFORE SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 5 
AFTER SWAP: v[0] = 5, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 1 
========== 
BEFORE SWAP: v[0] = 5, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 1 
AFTER SWAP: v[0] = 5, v[1] = 4, v[2] = 3, v[3] = 2, v[4] = 1 
========== 
BEFORE SWAP: v[0] = 5, v[1] = 4, v[2] = 3, v[3] = 2, v[4] = 1 
AFTER SWAP: v[0] = 5, v[1] = 4, v[2] = 3, v[3] = 2, v[4] = 1 
========== 
BEFORE SWAP: v[0] = 5, v[1] = 4, v[2] = 3, v[3] = 2, v[4] = 1 
AFTER SWAP: v[0] = 5, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 1 
========== 
BEFORE SWAP: v[0] = 5, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 1 
AFTER SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 5 
========== 

Что происходит с петлей auto? Почему я теряю ценности?

Вот ссылка CPP.SH, чтобы увидеть для себя: http://cpp.sh/2ve3

+1

Подобно Абхишеку, в итераторе альтернатива 'it' является логически ссылкой на векторный элемент, но' auto a' является просто копией. Попробуйте 'auto & a', и он должен работать так, как ожидалось. – enobayram

+0

@enobayram Это работает. Мне всегда казалось, что 'auto a' в этом случае уже есть ссылки. –

+1

обратите внимание также, что самая неприятная проблема синтаксического анализа в 'C++' относится к чему-то совершенно другому. –

ответ

3

с for(auto a : v) вы фактически получаете копию значения, а не в месте значения в массиве. Вы должны указать, что вы на самом деле хотите, ссылку на него, объявив петлю, как for(auto&a : v)

Функционирующий пример:

for (auto& a : v) 
{ 
    std::cout << "BEFORE SWAP: v[0] = " << *v[0] << ", v[1] = " << *v[1] << ", v[2] = " << *v[2] << ", v[3] = " << *v[3] << ", v[4] = " << *v[4] << std::endl; 
    std::swap(a, v[y]); 
    std::cout << "AFTER SWAP: v[0] = " << *v[0] << ", v[1] = " << *v[1] << ", v[2] = " << *v[2] << ", v[3] = " << *v[3] << ", v[4] = " << *v[4] << std::endl; 
    std::cout << "==========" << std::endl; 
    --y; 
} 

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

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

std::reverse(myvector.begin(),myvector.end()); 

Пример по адресу: http://www.cplusplus.com/reference/algorithm/reverse/?kw=reverse

+0

Я буду отмечать это как правильно, так как я не могу отметить комментарии, сделанные @enobayram как таковые. Кроме того, изменение вектора не было моей целью; вы можете удалить его, если хотите. –

0

Здесь копия значение вашего массива сохраняется в переменной «a». a не является ссылкой на значение массива ура. Именно поэтому, когда вы меняете две переменные, они меняются местами, но в переменной a. Нет в фактическом значении массива. И поскольку ур другим параметром swap является значением массива, он принимает значение переменной a. Вот почему u r не получает желаемого результата. Заявление авто а: v на самом деле утверждение, как показано ниже:

a=v[0]; 
a=v[1]; (on next iteration) 

И так далее. Как вы видите, a имеет только копию значения массива, а не ссылку. Вот почему вы получаете такой выход.

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