2016-11-18 3 views
0

Как глубоко стереть вектор?C++ STL vector Deep erase

Рассмотрите следующий код.

#include<algorithm> 
#include<iostream> 
#include<iterator> 
#include<vector> 

using namespace std; 

int main(){ 
    vector<int> v {1,2,3,4,5}; 
    for_each(begin(v),end(v),[&v](int& n){ 
     static auto i = (int)0; 
     if(n == 2){ 
      v.erase (begin(v) +2, end(v)); 
     } 
     cout << n << " having index " << i++ << endl; 
    }); 
    v.erase (begin(v) +2, end(v)); 
    cout << v.size() << endl << v[4] << endl; 
} 

Выход

1 having index 0 
2 having index 1 
3 having index 2 
4 having index 3 
5 having index 4 
2 
4 

То, что я хочу, обращается к V [я] для любого я от 2 до 4 недействительным и компилятор выдаст ошибку.

В более простых словах, как глубоко стереть вектор?

+2

Это UB; вы должны проверить его самостоятельно. Вместо этого используйте 'std :: vector :: at'. – songyuanyao

+0

вектор сохраняет свой элемент в смежной памяти по определению, поэтому то, что вы хотите, не возможно – user463035818

+1

И вы даже хотите, чтобы это была ошибка времени компиляции. – LogicStuff

ответ

1

Вы запускаете неопределенное поведение, и поэтому вашим результатам нельзя доверять.

Если вам необходимо проверить границы использования std::vector::at

vector<int> v{ 1,2,3,4,5 }; 
v.erase(begin(v) + 2, end(v)); 
try { 
    auto val = v.at(4); 
} catch (std::out_of_range&) { 
    cout << "out of range"; 
} 

Если вы не закодировать свой собственный объект или обходной путь, вы не можете иметь такие проверки во время компиляции с std::vector. Дополнительная информация и некоторые предложения здесь: https://stackoverflow.com/a/32660677/1938163

+0

В чем разница между доступом к оператору [] и методом? – kalpa

+0

@kalpa 'at' делает привязку проверки и выбрасывает исключение во время выполнения, если оно вне диапазона –

+0

Неправильная практика доступа к векторам с помощью' [] '? – kalpa

1

У меня нет времени прямо сейчас, чтобы привести примеры, но единственный способ, по которому я могу это сделать, - сделать либо собственный класс для переноса, либо подкласса. Затем вы можете создать пользовательские операторы [] и at, которые выдают ошибку для определенных индексов. У вас может быть даже метод удаления, который добавляет в этот список запрещенных.

Теперь, если вам нужна ошибка во время компиляции, это сложнее. Я думаю, что что-то может быть возможно с помощью оператора доступа constexpr и некоторых static_assert с, но я точно не уверен, как это делается.

+0

Если 'operator []' дает UB и не выполняет проверки диапазона, то почему это разрешено? Также 'at' добавляет служебные данные производительности по сравнению с' operator [] '? Если да, то насколько это значимо? – kalpa

+0

@kalpa Второе предложение вашего комментария отвечает на первое, [] существует как на медленном, точно, как медленно зависит, но я бы предположил, что в 3-10 раз больше времени для запуска. – Vality

+0

Другая вещь, когда я называю метод 'erase' или' clean', является освобожденной памятью или не освобождается, пока весь вектор не будет уничтожен? – kalpa