Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>А как выяснилось, что невалиден?
ну...данные затираются.
я как-то не подумал что возможно внутрях может выполняеться что-то типа memset()... ща проверю!
SVZ>Это где такое? ОСь, версия stl?
ubuntu-18.04, GCC-8.4.0
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
X>адрес не изменяется
В общем-то это не случайность и не прихоть реализации. Он гарантированно не будет меняться, так как resize делается на размер не превышающий capacity().
X>но данные затираются!
Какие данные? В твоём примере вектор пуст до момента вызова resize. Как может затереться то, чего нет?
X>в любом случае такое поведение мне кажется ошибочным...
Какое поведение?
Здравствуйте, _NN_, Вы писали:
_NN>Закрался вопрос, а как именно работаем с beg ?
кладем в него данные, т.е. разыменовываем.
_NN>Единственное, что мы получаем это указатель, который нельзя разыменовывать.
почему нельзя? reserve() ведь выделяет память, а data() возвращает указатель на выделенную память.
что не так?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, niXman, Вы писали:
X>почему нельзя? reserve() ведь выделяет память, а data() возвращает указатель на выделенную память. X>что не так?
Не так тут то, что reserve() _может_ аллоцировать память, но не добавляет элементы в массив.
Сперва нужно положить элементы в массив, а потом уже работать с ними.
ИМХО зря в вектор добавили метод data().
&vec[0] — законный, валидный способ достучаться до памяти.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>Не так тут то, что reserve() _может_ аллоцировать память, но не добавляет элементы в массив.
это именно то, что мне и нужно.
мне не нужен push_back() или подобные.
но так как reserve() аллоцирует память, и так как я могу получить ее используя 'operator[]' или 'data()' — я не вижу тут притиворечий.
даже в доке я ничего не нашел по моему случаю.
SVZ>ИМХО зря в вектор добавили метод data(). SVZ>&vec[0] — законный, валидный способ достучаться до памяти.
так а 'data()' чем мешает?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, niXman, Вы писали:
X>Здравствуйте, _NN_, Вы писали:
_NN>>Закрался вопрос, а как именно работаем с beg ? X>кладем в него данные, т.е. разыменовываем.
_NN>>Единственное, что мы получаем это указатель, который нельзя разыменовывать. X>почему нельзя? reserve() ведь выделяет память, а data() возвращает указатель на выделенную память. X>что не так?
Потому что это не так.
Память то выделяем, но указатель из data может не указывать на эту область.
Returns pointer to the underlying array serving as element storage. The pointer is such that range [data(); data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable in that case).
Валидным будет только полуинтервал data() — data + size().
size() у нас 0, потому что мы только зарезервировали, но не изменили размер.
Получаем полуинтервал [ data() ; data ), т.е. разыменовывать нельзя.
Здравствуйте, niXman, Вы писали:
SVZ>>Не так тут то, что reserve() _может_ аллоцировать память, но не добавляет элементы в массив.
X>это именно то, что мне и нужно. X>мне не нужен push_back() или подобные.
Ну у вектора определенная семантика и твой юзкейс явно в неё не вписывается.
X>но так как reserve() аллоцирует память, и так как я могу получить ее используя 'operator[]' или 'data()' — я не вижу тут притиворечий. X>даже в доке я ничего не нашел по моему случаю.
SVZ>>ИМХО зря в вектор добавили метод data(). SVZ>>&vec[0] — законный, валидный способ достучаться до памяти.
X>так а 'data()' чем мешает?
Позволяет использовать вектор не по назначению, как в твоём примере.
Мне просто не очень понятно, какую задачу ты решаешь.
Если нужен "буфер + RAII", то передавай в к-тор число элементов.
Ну или вместо reserve дергай resize().
_____________________
С уважением,
Stanislav V. Zudin
_NN>Returns pointer to the underlying array serving as element storage. The pointer is such that range [data(); data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable in that case).
_NN>Валидным будет только полуинтервал data() — data + size(). _NN>size() у нас 0, потому что мы только зарезервировали, но не изменили размер. _NN>Получаем полуинтервал [ data() ; data ), т.е. разыменовывать нельзя.
с формальной точки зрения ты прав, да.
но с практической — как бы нет =)
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, niXman, Вы писали:
X>с формальной точки зрения ты прав, да.
X>но с практической — как бы нет =)
С практической точки зрения можно делать и const_cast<char*>(myStdString.c_str()) , но мы тогда закладываемся на определённую реалзиацию.
Если нужно именно такое поведение от вектора, то нужно в кода указать требования компилятора:
#if COMPILER IS GCC AND VERSION == 1.2.3.4 AND PLATFORM = x86 ...
vec.resere(...)
*vec.data() = 1;
#else
#error Must use only supported compiler
#endif
А самый главный вопрос зачем это нужно ?
Если нужно просто выделить память и использовать то простейший вариант make_unique<int[]>(10);
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>зря в вектор добавили метод data(). SVZ>&vec[0] — законный, валидный способ достучаться до памяти.
Пара причин:
&vec[0] будет неправильно работать для типов с перегруженным operator&; data() возвращает валидный указатель для пустого вектора (хоть его и нельзя разыменовывать), а &vec[0] приводит к UB.
Во втором случае это позволяет значительно удобнее передавать содержимое вектора во другие функции:
Здравствуйте, _NN_, Вы писали:
_NN>Если нужно именно такое поведение от вектора, то нужно в кода указать требования компилятора: _NN>
_NN>#if COMPILER IS GCC AND VERSION == 1.2.3.4 AND PLATFORM = x86 ...
_NN>vec.resere(...)
_NN>*vec.data() = 1;
_NN>#else
_NN>#error Must use only supported compiler
_NN>#endif
_NN>
я не вижу в доках по reserve() никаких слов о том, что он может НЕ аллоцировать память в случае когда ты зовешь reserve() для пустого вектора и аргументом указано значение отличное от нуля.
_NN>А самый главный вопрос зачем это нужно ? _NN>Если нужно просто выделить память и использовать то простейший вариант make_unique<int[]>(10);
да, нужно просто выделить кусок памяти. с вектором казалось проще.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, niXman, Вы писали:
X>я не вижу в доках по reserve() никаких слов о том, что он может НЕ аллоцировать память в случае когда ты зовешь reserve() для пустого вектора и аргументом указано значение отличное от нуля.
Здравствуйте, niXman, Вы писали:
X>да и по логике — оно должно работать везде, иначе получится что reserve() сломан!
Reserve выделит всё правильно, но для пустого вектора data может вернуть не указатель на выделенную память, а что-то другое. Например, в отладочном режиме я бы так и сделал, чтобы обнаруживать ошибки при обращении.