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

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


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

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


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

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


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

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

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

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

ЗЫ
Приведите простой кейс использования. А то абстрактно советовать можно только коня в вакууме.
...
Рейтинг: 0 / 0
29.10.2015, 10:06
    #39089576
wst
wst
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
копирование в std::vector
Так и не понял задачи. Есть коллекция из строк, надо чтобы где-то неизвестное время болтался указатель на данные из этих строк одновременно с действиями над этой коллекцией? То есть туда лезут несколько потоков?
...
Рейтинг: 0 / 0
29.10.2015, 23:24
    #39090625
alexy_black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
копирование в std::vector
это асинхронный веб сервер. я сделал интерфейс на 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
30.10.2015, 00:39
    #39090652
BagaBaga
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
копирование в std::vector
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
30.10.2015, 13:18
    #39091050
alexy_black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
копирование в std::vector
BagaBaga, это ответ на мой вопрос, спасибо :) я раньше эту функцию c_str() почти никогда не использовал, так что не знаю тонокстей работы с ней.

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

а выстреливает она почему? потому что буфер, на который указатель нацелен, сразу же исчезает или потому что он не известно когда исчезает?
...
Рейтинг: 0 / 0
30.10.2015, 23:07
    #39091594
BagaBaga
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
копирование в std::vector
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
31.10.2015, 10:50
    #39091664
Гость123
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
копирование в std::vector
Я думал, что:
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
31.10.2015, 11:30
    #39091672
BagaBaga
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
копирование в std::vector
Гость123,
с семафорами, атомиками и многопоточным программированием всё гораздо сложнее - там нужно понимать C++ memory model (в частности барьеры).

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

Если сомневаетесь, что компилятор "вычищает" и "переупорядочивает"... скомпилируйте простенький код с самыми агрессивными настройками оптимизации и без них и посмотрите в дизассемблере. Там вас уж точно ни кто не обманет.
...
Рейтинг: 0 / 0
05.11.2015, 01:10
    #39094763
Пётр Седов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
копирование в std::vector
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
Форумы / C++ [игнор отключен] [закрыт для гостей] / копирование в std::vector / 12 сообщений из 12, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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