STL Вопросы миграции (VS 2003 -> 2005) - PullRequest
2 голосов
/ 12 ноября 2008

Я только что преобразовал проект из Visual Studio 2003 в 2005, и хотя большая часть его «преобразована» нормально, у меня есть ряд ошибок STL из следующей строки:

void SomeFn( std::vector<CSomeObject*>::iterator it,
std::vector<CSomeObject*>::iterator itBegin = NULL,
std::vector<CSomeObject*>::iterator itEnd = NULL );

Ошибка Visual Studio выглядит следующим образом:

c:\<path>\Headerfile.h(20) : error C2440: 'default argument' : cannot convert from 'int' to 'std::_Vector_iterator<_Ty,_Alloc>'
        with
        [
            _Ty=CObject *,
            _Alloc=std::allocator<CObject *>
        ]
        No constructor could take the source type, or constructor overload resolution was ambiguous

Я не вижу ничего плохого в этом коде, и он отлично работал в VS 2003. Есть идеи?

Ответы [ 2 ]

11 голосов
/ 12 ноября 2008

Ваша программа неверна, так как NULL не может быть преобразован как итератор. Я действительно не знаю, что вы хотите, чтобы эти итераторы были инициализированы как. Если вам нужен итератор, который гарантированно не будет находиться в контейнере, а будет «действительным», вы можете использовать конструктор по умолчанию:

typedef std::vector<CSomeObject*> myvector_t;
void SomeFn( myvector_t::iterator it,
             myvector_t::iterator itBegin = myvector_t::iterator(),
             myvector_t::iterator itEnd = myvector_t::iterator() );

Обратите внимание, однако, что если вы сделаете это, it, itBegin и itEnd не будут сопоставимы по значимости! Только итераторы, полученные из данного контейнера, по смыслу сопоставимы. В конце я бы рекомендовал не использовать значения по умолчанию для itBegin и itEnd. Если вам действительно их не нужно, создайте другую функцию без аргументов и сделайте что-то значимое. i.e.:

typedef std::vector<CSomeObject*> myvector_t;
void SomeFn( myvector_t::iterator it,
             myvector_t::iterator itBegin,
             myvector_t::iterator itEnd );
void SomeFn( myvector_t::iterator it ); // No begin/end arguments

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

2 голосов
/ 12 ноября 2008

В 2003 году std::vector<T>::iterator - это просто T *. В 2005 году, по крайней мере, в режиме отладки, это класс, и поэтому вы не можете использовать NULL для его значения (NULL разрешается до 0).

Вместо этого вы можете использовать построенный по умолчанию итератор:

std::vector<CSomeObject*>::iterator itBegin = std::vector<CSomeObject*>::iterator()
...