powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / копирование в std::vector
12 сообщений из 12, страница 1 из 1
копирование в std::vector
    #39088445
alexy_black
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
использую код на c в него нужно передать указатель на char . я его получаю с помощью c_str у std::string . такой указатель жив пока живет строка, от куда я его поулчил и пока она с того момента не изменилась.

но вот если эта строка живет (и никто её не изменяет) в std::vector - то будет ли работать c_str или накроется при каком-нибудь std::find ?
...
Рейтинг: 0 / 0
копирование в std::vector
    #39088531
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexy_blackиспользую код на c в него нужно передать указатель на char . я его получаю с помощью c_str у std::string .


Указатель на char невозможно получить с помощью функции c_str(), потому что она возвращает const char*

Чтобы получить указатель на буфер std::string надо взять адрес первого элемента строки или использвать функцию front()


акой указатель жив пока живет строка, от куда я его поулчил и пока она с того момента не изменилась.
-- ДА.

но вот если эта строка живет (и никто её не изменяет) в std::vector - то будет ли работать c_str или накроется при каком-нибудь std::find?


Это не важно, где живёт сама строка. Но разумеется, она не должна уничтожаться.
...
Рейтинг: 0 / 0
копирование в std::vector
    #39088962
alexy_black
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
конечно не должна уничтожаться...
вопрос появился из невозможности нормлаьного использования std::vector<std::auto_ptr<foo>> ( std::vector<std::unique_ptr<foo>> ), потому что некторые алгоритмы работы с контейнерами и реализация контейнера будут копировать объекты, а при копировании исходный объект удалиться (в случаи этих ptr'ов).

вот я и подумал: что останется в векторе, копия когда-нибдуь и ли всегда будет исходная строка?

ну да, const , но даже если я возьму адрес начала строки ( std::string::data() вроде подходит ), то вопрос остается актуальным :)
...
Рейтинг: 0 / 0
копирование в std::vector
    #39089419
BagaBaga
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexy_black,
не используйте auto_ptr. Он сейчас запрещен к использованию, и разработчики большинства реализаций стандартных библиотек сделали всё, чтобы auto_ptr нельзя было использовать на стандартных контейнерах - должны порождаться ошибки компиляции. Если вам необходимо монопольное владение ресурсом, используйте unique_ptr. Если нужно совместное ("разделяемое") владение - используйте shared_ptr.

Какая разница, где живёт эта строка? Лишь бы она не вышла за область своей видимости (и не была "почищена" деструктором).

ЗЫ
Приведите простой кейс использования. А то абстрактно советовать можно только коня в вакууме.
...
Рейтинг: 0 / 0
копирование в std::vector
    #39089576
wst
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так и не понял задачи. Есть коллекция из строк, надо чтобы где-то неизвестное время болтался указатель на данные из этих строк одновременно с действиями над этой коллекцией? То есть туда лезут несколько потоков?
...
Рейтинг: 0 / 0
копирование в std::vector
    #39090625
alexy_black
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
это асинхронный веб сервер. я сделал интерфейс на c++ но код сервера написан на с (libh2o). отправка происходит асинхронно, поэтому я копирую некоторые строки, когда пользователь вызывает функцию отправки, потом, когда-то, они будут отправлены. ну смысл такой.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
std::vector<std::string> strings;
push_some_strings_to_vector(strings);

assert( strings.size()>0 ); // true
const char* pointer_to_c_str = strings[0].c_str();

// do something with stings
std::find(strings.begin(),strings.end(),"42");
// std::find_if
// std::...

// и что тут происходит? этот адрес еще на месте?
std::cout << std::strign(pointer_to_c_str) << std::endl;



да, про auto_ptr знаю, не использую :) просто я напаролся один раз (давно) на конструкции вида std::vector<std::auto_ptr<foo>> :) то есть хранились они хорошо, но как только применил какой-то алгоритм, все пропадало :) это пому что этот алгоритм там внутрях что-то копировал, а auto_ptr передавал владение копии, которая уничтожалась вместе с объектом.
...
Рейтинг: 0 / 0
копирование в std::vector
    #39090652
BagaBaga
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexy_black,
не делайте так:
alexy_black...
Код: plaintext
1.
2.
3.
4.
...
const char* pointer_to_c_str = strings[0].c_str();
...
std::cout << std::strign(pointer_to_c_str) << std::endl;


...
Время "валидности" полученного вами указателя ограничено строкой "const char* pointer_to_c_str = strings[0].c_str();". Ровно до точки с запятой. После этой строки может произойти инвалидация указателя (стандарт не гарантирует вам сохранение его "валидности"). Это происходит не часть, и потому такой код довольно долго работает... но в один прекрасный момент может выстрелить. Ваш пример можно переделать к "законному" виду:
Код: plaintext
1.
std::cout << std::strign(strings[0].c_str()) << std::endl;


Здесь указатель живёт сколько надо. Вот только в данном примере это не имеет смысла (т.к. cout прекрасно понимает std::string).
...
Рейтинг: 0 / 0
копирование в std::vector
    #39091050
alexy_black
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BagaBaga, это ответ на мой вопрос, спасибо :) я раньше эту функцию c_str() почти никогда не использовал, так что не знаю тонокстей работы с ней.

да, я знаю что cout понимает std::string - но в коде я не cout использую, а api функцию на c, которая ничего не понимает кроме char* . это просто для "примера использования".

а выстреливает она почему? потому что буфер, на который указатель нацелен, сразу же исчезает или потому что он не известно когда исчезает?
...
Рейтинг: 0 / 0
копирование в std::vector
    #39091594
BagaBaga
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexy_black,
такое поведение - не особенность функции c_str.

Что c_str делает? Возвращает указатель на внутреннюю структуру (буфер). Сколько этот указатель будет валидным? Не более, чем "жива" сама структура (пока она не уйдёт из области видимости). Но может быть "испорчена" и ранее, если происходили изменения структуры (например, "склеивали" строки и для новой "итоговой" строки пришлось получать новый буфер). Что делать? Во-первых, не менять строку после того, как получил указатель (иначе мы его можем инвалидировать). Теперь осталось разобраться со временем жизни. Какое оно? Что сделает компилятор вот на это:
Код: plaintext
1.
2.
3.
string str;
const char * const ch = str.c_str();
*ch;


?

Он может сделать, например, вот так
Код: plaintext
1.
2.
3.
4.
str.string(); // конструктор
const char * const ch = str.c_str();
str.~string(); // деструктор
*ch;


Почему? Что нам гарантирует стандарт?
- Что конструктор обязательно будет вызван до первого "использования" экземляра класса. Скорее всего, в месте объявления, но не обязательно.
- Что деструктор будет вызван перед "окончанием" области видимости. Где-то перед, а не обязательно "точно вот перед выходом". Но обязательно после последнего "использования".

Компилятор имеет право переупорядочивать инструкции. Например, в целях оптимизации скорости выполнения. И в данном примере он может (но не обязано - без гарантий) вызвать деструктор после последнего использования (str.c_str()), но до нашего обращения к "нутру" этого объекта (*ch). Компилятор спокойно отслеживает все обращения типа str.чего_то_там, но различного рода косвенные обращения он отследить не в состоянии. В результате наше последующее обращение по полученному через c_str() адресу может быть невалидным - этот адрес может быть уже освобождён (вызовом деструктора) и повторно использован кем-либо ещё.

Почему может выстрелить? Потому что эта память может быть кем-то использована на запись и мы пользуем "чужую", уже "подпорченную" область. В большинстве случаев эта память "лежит спокойно" и никому не достаётся - в результате мы спокойно видим старые и даже неподпорченные данные. Вероятность порчи этих данных зависит от - опций компиляции, способа использования приложения. Если опция компиляции не больше -О2, то переупорядочивание вызова деструктора обычно (но - без гарантий) не происходит. Если -O3, то почти наверняка переупорядочит. Если приложение многопоточное и-или интенсивно использует память - то больше шансов, что память, из которой мы читает по "внутреннему" указателю, будет выделена для конкурирующего потока. И вот тогда приложение сломается, получая вместо "хорошей" строки "непонятный мусор".

Так что если коротко ответить на вопрос: одному компилятору известно, когда он исчезает
...
Рейтинг: 0 / 0
копирование в std::vector
    #39091664
Гость123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я думал, что:
Local objects explicitly declared auto or register or not explicitly declared static or extern have automatic storage duration. The storage for these objects lasts until the block in which they are created exits.
Означает, что объект живёт до завершения блока, в котором он объявлен. Однако если это не так, то может кто-нибудь объяснить на каком основании должно работать RAII?
Вот мы пишем скажем:
Код: plaintext
1.
2.
3.
4.
{
MutexLock lock(mutex);
// работаем с расшаренными данными
}// думаем, что деструктор lock будет вызван здесь


Но получается, что оно может отработать и так:
Код: plaintext
1.
2.
3.
4.
5.
{
MutexLock lock(mutex);
// Вызов деструктора lock
// работаем с расшаренными данными
}
...
Рейтинг: 0 / 0
копирование в std::vector
    #39091672
BagaBaga
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гость123,
с семафорами, атомиками и многопоточным программированием всё гораздо сложнее - там нужно понимать C++ memory model (в частности барьеры).

Про RAII. Суть RAII - "обернуть" незащищённый ресурс и везде вместо него использовать обёртку. Тот же unique_ptr существует (гарантированно существует) до тех пор, пока к нему есть "обращения". Вы не можете оберныть "грязный" указатель в умный и продолжать безнаказанно пользоваться "грязным" - рано или поздно выстрелит.

Если сомневаетесь, что компилятор "вычищает" и "переупорядочивает"... скомпилируйте простенький код с самыми агрессивными настройками оптимизации и без них и посмотрите в дизассемблере. Там вас уж точно ни кто не обманет.
...
Рейтинг: 0 / 0
копирование в std::vector
    #39094763
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BagaBagaЧто сделает компилятор вот на это:
Код: plaintext
1.
2.
3.
string str;
const char * const ch = str.c_str();
*ch;


?

Он может сделать, например, вот так
Код: plaintext
1.
2.
3.
4.
str.string(); // конструктор
const char * const ch = str.c_str();
str.~string(); // деструктор
*ch;

Нет, не может.

BagaBagaКомпилятор имеет право переупорядочивать инструкции. Машинные инструкции, а не statement-ы языка, и только так, чтобы наблюдаемое поведение программы не изменилось.

BagaBagaИ в данном примере он может (но не обязано - без гарантий) вызвать деструктор после последнего использования (str.c_str()), но до нашего обращения к "нутру" этого объекта (*ch).Нет, не может.

Гость123Я думал, что:
Local objects explicitly declared auto or register or not explicitly declared static or extern have automatic storage duration. The storage for these objects lasts until the block in which they are created exits.
Означает, что объект живёт до завершения блока, в котором он объявлен. Однако если это не так, то может кто-нибудь объяснить на каком основании должно работать RAII?RAII работает на том основании, что BagaBaga написал неправду :).

Гость123Вот мы пишем скажем:
Код: plaintext
1.
2.
3.
4.
{
MutexLock lock(mutex);
// работаем с расшаренными данными
}// думаем, что деструктор lock будет вызван здесь


Но получается, что оно может отработать и так:
Код: plaintext
1.
2.
3.
4.
5.
{
MutexLock lock(mutex);
// Вызов деструктора lock
// работаем с расшаренными данными
}

Нет, не может.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / копирование в std::vector
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]