Russian Qt Forum

Программирование => С/C++ => Тема начата: sidsukana от Апрель 20, 2012, 11:54



Название: stl контейнер и указатели
Отправлено: sidsukana от Апрель 20, 2012, 11:54
Добрый день. Есть такая проблемка, нуждаюсь в помощи матерых :)
Имееются векторы структур в векторе

Код
C++ (Qt)
struct Cell
{
   union
   {
       uint32 u;
       int32 i;
       float f;
       char* s;
   }
};
vector<vector<Cell>> dataTable;

Данные в ячейке всегда в первых 3 типах, а char* нужен чтобы отдельно потом туда положить указатель на строку.

Вот пример. Допустим в 3 поле мне надо положить строку из другого вектора с помощью указателя.

Код
C++ (Qt)
 
vector<string> strings("123", "456", "789");
 
vector<Cell> v = dataTable.at(0);
v[2].s = (char*)strings.at(0).c_str();
// Теперь если смотреть в отладке в v[2].s содержится "123"

Далее, я хочу в 5 ячейку также поместить другую строку

Код
C++ (Qt)
v[4].s = (char*)strings.at(1).c_str();
// Смотрим в отладке - видим что v[2].s теперь стало "456", а указатели абсолютно одинаковые.

Объясните мне эту соль в С++ ,а то не докуриваю что не так и почему так происходит))


Название: Re: stl контейнер и указатели
Отправлено: Igors от Апрель 20, 2012, 12:27
Впечатление что Вы приводите текст "для примера" - а ответ нужен конкретный  :)
Код
C++ (Qt)
vector<string> strings("123", "456", "789");
 
Не знаю такого конструктора вектора

Если Вы почистите код и будете использовать const как положено - то вероятно само и рассосется  :)


Название: Re: stl контейнер и указатели
Отправлено: mutineer от Апрель 20, 2012, 12:31
Цитировать
The returned array points to an internal location with the required storage space for this sequence of characters plus its terminating null-character, but the values in this array should not be modified in the program and are only guaranteed to remain unchanged until the next call to a non-constant member function of the string object.

Не стоит сохранять вернувшийся из c_str указатель, так как содержимое этой области памяти может измениться


Название: Re: stl контейнер и указатели
Отправлено: Igors от Апрель 20, 2012, 12:59
Не стоит сохранять вернувшийся из c_str указатель, так как содержимое этой области памяти может измениться
Ну если нет никаких модификаций - то чего ему меняться? Но зачем городить вектор <std::string> если эти строки все равно "только чтение"? Просто так
Код
C++ (Qt)
const char * theStrings[] = { "123", "456", "789" };
 


Название: Re: stl контейнер и указатели
Отправлено: sidsukana от Апрель 20, 2012, 13:05
Впечатление что Вы приводите текст "для примера" - а ответ нужен конкретный  :)
Код
C++ (Qt)
vector<string> strings("123", "456", "789");
 
Не знаю такого конструктора вектора

Если Вы почистите код и будете использовать const как положено - то вероятно само и рассосется  :)
Ну создание вектора таким образом я для примера написал)) весь код дома к сожалению, а сейчас на работе) Но я думаю вы поняли что я имел ввиду вектор из 3 элементов))


Название: Re: stl контейнер и указатели
Отправлено: sidsukana от Апрель 20, 2012, 13:06
Не стоит сохранять вернувшийся из c_str указатель, так как содержимое этой области памяти может измениться
Ну если нет никаких модификаций - то чего ему меняться? Но зачем городить вектор <std::string> если эти строки все равно "только чтение"? Просто так
Код
C++ (Qt)
const char * theStrings[] = { "123", "456", "789" };
 

Нет, массив должен быть динамический. :)


Название: Re: stl контейнер и указатели
Отправлено: Igors от Апрель 20, 2012, 13:14
Нет, массив должен быть динамический. :)
Тогда никак не вектор, потому что у него адреса элементов уплывают при добавлении новых элементов - причем не всякий раз, а подленько. Используйте напр std::list или std;;dequeu

И const все-таки лучше писать, а то ужасная анти-санитария


Название: Re: stl контейнер и указатели
Отправлено: sidsukana от Апрель 20, 2012, 13:39
Ну я заполняю массив заранее и в дальнейшем его уже не меняю. Заполняю его из файла. Поэтому динамический.


Название: Re: stl контейнер и указатели
Отправлено: Igors от Апрель 20, 2012, 16:14
Ну я заполняю массив заранее и в дальнейшем его уже не меняю. Заполняю его из файла. Поэтому динамический.
Вместо того чтобы пререкаться "меняю- не меняю" просто используйте более подходящий контейнер. А потом поговорим


Название: Re: stl контейнер и указатели
Отправлено: V1KT0P от Апрель 20, 2012, 16:24
Прочитал комментарии и ничего не понял =). Что хочет автор? Если получить массив чаров из кьюстринга, то вот решение:
Код
C++ (Qt)
char* charFromQString(QString &str)
{
   char *tmp = new char[str.length()+1];
   strncpy(tmp, str.toLocal8Bit(), str.length());
   tmp[str.length()] = 0;
   return tmp;
}
 
v[2].s = charFromQString(strings.at(0));


Название: Re: stl контейнер и указатели
Отправлено: sidsukana от Апрель 20, 2012, 17:53
Помоему все ясно я написал - надо указатель на строку поместить в указатель что находится в структуре, которая является элементом массива.


Название: Re: stl контейнер и указатели
Отправлено: V1KT0P от Апрель 20, 2012, 18:23
Помоему все ясно я написал - надо указатель на строку поместить в указатель что находится в структуре, которая является элементом массива.
Блин не заметил что про стандартные стринги написано, тогда так:
Код
C++ (Qt)
char* charFromString(string &str)
{
   char *tmp = new char[str.length()+1];
   strncpy(tmp, str.c_str(), str.length());
   tmp[str.length()] = 0;
   return tmp;
}
Либо храни указатель не на чар а на стринг раз тебе только чтение необходимо. Никогда в жизни даже не думал хранить указатель на буфер чаров выданный каким-либо стринговым классом, ибо может много плохого случиться.


Название: Re: stl контейнер и указатели
Отправлено: sidsukana от Апрель 20, 2012, 18:55
Все проблему решил. В структуре Cell сделал указатель константным и без приведения типа присвоил его. Однако пришлось вектор тоже через pointer достать.

В общем вот так получилось у меня

Код
C++ (Qt)
template<typename T>
T* File::getRecord(uint32 id) const
{
   vector<vector<Cell>>::pointer v = getRecord(id);
 
   for (vector<uint32>::iterator itr = m_stringFields.begin(); itr != m_stringFields.end(); ++itr)
   {
       Cell* cell = &v->at(*itr);
       const char* str = m_stringsBlock.at(cell->u).c_str();
       cell->s = str;
   }
 
   return (T*)v->data();
}