2010-04-28 4 views
6

Иногда полезно использовать начальный адрес std::vector и временно рассматривать этот адрес как адрес регулярно распределяемого буфера.
Например заменить это:C++: получить адрес начала std :: vector?

char* buf = new char[size]; 
fillTheBuffer(buf, size); 
useTheBuffer(buf, size); 
delete[] buf; 

с этим:

vector<char> buf(size); 
fillTheBuffer(&buf[0], size); 
useTheBuffer(&buf[0], size); 

Преимущество этого, конечно, что буфер освобождается автоматически, и я не придется беспокоиться о delete[].

Проблема, с которой я столкнулся, заключается в том, когда размер == 0. В этом случае первая версия работает нормально. Пустой буфер «распределяется», а последующие функции ничего не делают размером, они получают размер == 0.
Вторая версия, однако, не работает, если размер == 0, так как вызов buf[0] может справедливо содержать утверждение, что 0 < size.

Так есть ли альтернатива идиоме &buf[0], которая возвращает адрес начала вектора, даже если вектор пуст?

Я также рассмотрел использование buf.begin(), но в соответствии со стандартом даже не гарантированно вернуть указатель.

+0

Это похоже на надзор в библиотеке STL. C++ позволяет вам выделять 'new T [0]' и возвращать действительный указатель для таких ситуаций, но большинство реализаций STL утверждают, что вы назначаете этот элемент или что-то еще. – AshleysBrain

+0

Как узнать разницу между '& buf [0]' и 'buf [0] = 1'? – shoosh

ответ

8

Думаю, вам просто нужно будет проверить.

Возможно, функция полезности:

template <class T, class Alloc> 
T* data(std::vector<T, Alloc>& vec) 
{ 
    return vec.empty() ? 0 : &vec[0]; 
} 

template <class T, class Alloc> 
const T* data(const std::vector<T, Alloc>& vec) 
{ 
    return vec.empty() ? 0 : &vec[0]; 
} 
+1

Первое замечание: стоит ли инвестировать в 'boost :: addressof', если' T' имеет перегруженный '&' оператор? Второе замечание: второй параметр шаблона 'Alloc' сделает функцию более универсальной. –

+1

@Matthieu: Что касается первого замечания: http://stackoverflow.com/questions/2719832/why-is-overloading-operator-prohibited-for-classes-stored-in-stl-containers. Вы не можете сохранить тип, для которого '& t' не возвращает свой адрес. Второе замечание добавлено в ответ. – UncleBens

1

Там нет функции для этого, даже если std::basic_string имеет data(), который делает именно то, что вам нужно.

Вы должны будете использовать что-то вроде buf.size()?&buf[0]:0;

1

Я думаю, вы должны быть безопасными в любом случае. Я считаю, что различия между vector :: operator [int] и vector :: at (int) заключаются в том, что перегрузка оператора [] специфически делает не выполняет проверку границ. Использование buf [0] должно быть свободным от утверждений!

+0

К сожалению, вы ошибаетесь. Вектор MSVC2008 имеет утверждения на 'operator []'. – shoosh

+0

Спасибо, что просветили меня! – acanaday

+4

В качестве продолжения я узнал, что следующее '#define _SECURE_SCL 0' отключит это поведение. – acanaday

1

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

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