PDA

Просмотр полной версии : std::vector


Crazy_kettle
29.01.2006, 02:22
возникли у меня проблемы с использованием класса vector из стандатрной библиотеки.
Компилятор MS Visual Studio .Net при выполнении следующего фрагмента:

#include <stdlib.h>
#include <iostream>
#include <conio.h>

using std::vector;
using std::cout;
using std::endl;

struct TS{
char* str;
int len;
TS():str(0),len(0){}
~TS(){
free(str);
str=0;
}
};
int main(){
TS s;
vector<TS> vec;
char* temp="This is string";
s.len=strlen(temp);
s.str=static_cast<char*>(malloc(s.len+1));
strcpy(s.str,temp);
cout<<s.str<<'\n';
vec.push_back(s);
cout<<(s.str==0)<<'\t'<<s.str<<'\n';
TS& el=vec.back();
cout<<(el.str==s.str)<<'\t'<<el.str<<endl;
s.str=0;//Чтобы деструктор не пытался освободить память повторно.
return 0;
}

выдаёт (к тому же возникает какая-то ошибка):

This is string
0 8RD
1 8RD


Причём, если убрать из структуры TS дескриптор, то выполняется на ура.
Только вот не пойму, причём здесь деструктор может быть причастен, ведь переменная s и вектор vec ещё используются (не говоря уже об области видимости)? Более того, как для переменной s, так и для vec.back(), он явно не вызывался, т.к. s.str==vec.back().str!=0.
Может, у кого идеи есть по поводу этой проблемы.

P.s. Такая "ботва" была обнаружена при отладке написанной программы, где такой подход был использован для того, чтобы при вызове vec.clear() автоматически освобождалась занятая память и при этом избежать "ненужных" выделений памяти и копирования. Вопрос 2: Что делать? Изменять char* на string не хочется, ибо нужно будет очень много править (везде идёт работа с C-строками). Конечно, можно, убрать деструктор и перед вызовом vec.clear() производить "чистку" или ввести новый класс

class myvector: public vector<TS>{
public:
void clear(){
for (int i=0;i<size();i++)
free((*this)[i].str);
vector<TS>::clear();
}
};

Может у вас есть более изящные предложения?

Drakosha
29.01.2006, 09:27
Во первых, на g++ 3.4.4 всё пашет
Во вторых, если где-то создаётся временный объект TS, например при выполенении этой строчки: vec.push_back(s); то деструктор может быть вызван им. Поэтомы для объектов с поинтерами всегда стоит писать operator= и copy constructor. Если написать их в private без имплементации, т.е. запретить, то компилятор даст ошибку в том месте где он хотел их использовать.
В третьих, лучше пользоваться new и delete т.к. они вызывают контруктор/деструктор в отличии от malloc/free. В этом примере это не важно imho.

Надеюсь помог

alexey_ma
29.01.2006, 21:47
2 Drakosha.
vec.push_back(s) не создает стековый обьект. push_back в параметре получает константный референс

void push_back(
const Type& _Val
);

Именно поэтому и происходит креш, вектор при добавлении элемента плоско копирует структуру. Получается две структуры имееющие указатель на один и тот -же адрес. Это христоматийная ошибка. На таких примерах обычно показывают зачем нужен копи-конструктор. Обьекты помещаемые в стандартные (stl) контейнеры должны иметь копи-конструкторы.


2 Crazy_kettle.
Что-то намешано у тебя и С и С++.
Вектор на самом деле при удалении элемента вызывет для него деструктор.
Попробуй хранить в векторе указатели на структуру TS, а не сами сами структуры, тогда сам сможешь управлять выделением и освобожденим пямяти. То есть что то типа

struct TS{
char* str;
int len;
TS():str(0),len(0){}
TS(const char* s) ///нормальный конструктор
{
len = strlen(s);
str= new char[len+1];
strcpy(str,s);
}
~TS(){
if(str)
delete [] str;
str=0;
}
};

int main ()
{
vector<TS*> vec;
///Это слишком длинно/////////
TS* pTS = new TS();//("This is string");
char* temp="This is string";
pTS->len = strlen(temp);
pTS->str = new char [pTS->len+1];
strcpy(pTS->str,temp);
/////Проще написать нормальный конструктор и сделать
/////так TS* pTS = new TS("This is string");
cout<<pTS->str<<'\n';
vec.push_back(pTS);
cout<<(pTS->str==0)<<'\t'<<pTS->str<<'\n';
//запомнить указатель
TS* pTS1 = vec.back();
cout<<(pTS1->str==pTS->str)<<'\t'<<pTS1->str<<endl;
///освобождение пямяти////////////
//удалить указатель из вектора
vec.pop_back(); /// еще можно так vec.erase(0) или vec.clear();
//удалить сам указатель
delete pTS1 ;

}

Crazy_kettle
29.01.2006, 22:54
Что-то намешано у тебя и С и С++.

Пишу как умею :). Начал недавно переходить с С на С++. С бинарными файлами на С++ я не работал ещё, поэтому решил изпользовать стандартную библиотеку С (чтобы не тратить лишнее время на поиск множества багов, кот. всегда выскакивают, когда начинаешь что-то изучать).

Именно поэтому и происходит креш, вектор при добавлении элемента плоско копирует структуру. Получается две структуры имееющие указатель на один и тот -же адрес. Это христоматийная ошибка.

Ошибка будет, если изменять строку и из вектора и из структуры, а если нет, то какая тут ошибка?
В проге структура используется только для инициализации и чтобы запихнуться в вектор.


Вектор на самом деле при удалении элемента вызывет для него деструктор.

Для этого деструктор и писался :). В первом посте это и написано. Проблема, только что нигде перед использованием НЕ удаляются элементы из вектора и как было также написано деструкторы элементов НЕ вызывались.

Во первых, на g++ 3.4.4 всё пашет
Во вторых, если где-то создаётся временный объект TS, например при выполенении этой строчки: vec.push_back(s); то деструктор может быть вызван им.

Да похоже программисты Microsoft что-то с STL перемудрили и действительно где-то у них создаётся временный объект. Хотя это мне кажется странным, т.к. для больших объектов из-за этого скорость должна сильно упасть!!!!!!

Поэтому для объектов с поинтерами всегда стоит писать operator= и copy constructor.

Дело в том, что писать их не хотелось, ибо каждая такая операция медленная и причём НЕнужная (Имхо).
З.Ы. Как я понял, изящней последнего решения (то, кот. с наследованием) в моём первом после ничего не придумано. Его я и реализовал.

Drakosha
30.01.2006, 11:13
alexey_ma:
2 Drakosha.
vec.push_back(s) не создает стековый обьект. push_back в параметре получает константный референс
Согласен частично. Т.е. во время передач в функцию временый обьект не создаётся. Но неизвестно какая там имплементация, всё таки где-то он копируется :). Кстати, в gcc не копируется :D
Crazy_kettle:
Да похоже программисты Microsoft что-то с STL перемудрили и действительно где-то у них создаётся временный объект. Хотя это мне кажется странным, т.к. для больших объектов из-за этого скорость должна сильно упасть!!!!!!
Crazy_kettle:
100% согласен
Дело в том, что писать их не хотелось, ибо каждая такая операция медленная и причём НЕнужная (Имхо).
З.Ы. Как я понял, изящней последнего решения (то, кот. с наследованием) в моём первом после ничего не придумано. Его я и реализовал.
Во первых, copy constructor и operator= всегда стоит написать или запретить. (Пользоваться дефолтным === написать)
Бо вторых, по моему правильное решение написать их все таки так как твоэ решени может упасть на каком-то другом сценарии - все так там возможна двойная деаллокация.

alexey_ma
30.01.2006, 12:22
Crazy_kettle:
Да похоже программисты Microsoft что-то с STL перемудрили и действительно где-то у них создаётся временный объект. Хотя это мне кажется странным, т.к. для больших объектов из-за этого скорость должна сильно упасть!!!!!!
Ничего тут мудрого нет. Повторяю еще раз медленно. Ты создал структуру (назовем его ts), при попытке добавления это структуры в в вектор создается новый обьект (назовем его ts1) , в ts1 копируется ts. Поскольку копи-конструктора у тебя нет, то копируется плоско - тоесть ПОБАЙТНО. В итоге получаем две структуры содержащие указатель на одну и ту-же область памяти. Для обеих структур вызывается деструктор (не обязательно при удалении из вектора, у тебя просто обьекты выходят из скопа, то есть кончается их время жизни) и пытается дважды освободить один и тот же указатель. В итоге креш. Я же писал Обьекты помещаемые в стандартные (stl) контейнеры должны иметь копи-конструкторы. . Не надо косить на Microsoft, лучше изучи как работать с STL. Это давно уже стандарт языка С++. И писать надо не как умею , а как того требуют правила языка. Не стыдно быть чайником - стыдно им оставаться.

Drakosha
Но неизвестно какая там имплементация, всё таки где-то он копируется

Еще как известно. STL - это библиотека шаблонов и поставляется в исходниках

PSyton
30.01.2006, 13:24
Пишу как умею :). Начал недавно переходить с С на С++. С бинарными файлами на С++ я не работал ещё, поэтому решил изпользовать стандартную библиотеку С (чтобы не тратить лишнее время на поиск множества багов, кот. всегда выскакивают, когда начинаешь что-то изучать).
...
Да похоже программисты Microsoft что-то с STL перемудрили и действительно где-то у них создаётся временный объект. Хотя это мне кажется странным, т.к. для больших объектов из-за этого скорость должна сильно упасть!!!!!!

Прошу прощения за повтор, но все же...
Уважаемый, MS тут не причем. STL он и в Африке STL. И в доках четко и ясно написано что конструкторы копирования и операция присваивания для пользовательских классов при хранении их не по указателю необходимы.

Crazy_kettle
30.01.2006, 20:00
Во первых, copy constructor и operator= всегда стоит написать или запретить. (Пользоваться дефолтным === написать)
Если запретить, то имхо в вектор ничего нельзя будет добавить :(. Кстати, Имхо вызов конструктора не вредит. Другое дело деструктор, но его я убрал :). Память освобождается при очистке вектора. Да это решение не идеально, т.к. нужно иметь ввиду возможные кросс-референсы и memory-leaks (при использовании комманд копирования и изменения вектора, отличной от clear). Но это на данный момент не используется! Более того, написав copy constructor и operator=, я потеряю в скорости, т.к. будет происходить как минимум 2 НЕ ОБЯЗАТЕЛЬНЫХ копирований строки (от одного можно избавиться, но не от второго :( ).
[hr]
Ты создал структуру (назовем его ts), при попытке добавления это структуры в в вектор создается новый обьект (назовем его ts1) , в ts1 копируется ts. Поскольку копи-конструктора у тебя нет, то копируется плоско - тоесть ПОБАЙТНО. В итоге получаем две структуры содержащие указатель на одну и ту-же область памяти. Для обеих структур вызывается деструктор (не обязательно при удалении из вектора, у тебя просто обьекты выходят из скопа, то есть кончается их время жизни) и пытается дважды освободить один и тот же указатель. В итоге креш.
Ну это я знаю и имею ввиду. Только, кажется, ваше объяснение НЕ подходит. Я же писал:
переменная s и вектор vec ещё используются (не говоря уже об области видимости)
Более того, как для переменной s, так и для vec.back(), он(деструктор) явно не вызывался, т.к. s.str==vec.back().str!=0.
Более того, ту возможность, о которой вы писали, я предусмотрел:
s.str=0;//Чтобы деструктор не пытался освободить память повторно.
Да при окончании программы вызывается деструктор для строки. Но т.к. s.str==NULL, то ф-ция free(s.str) НИЧЕГО не делает, а, значит, можно считать, что для структуры s деструктор вовсе отсутствует :).
Не предусмотрел я то, что при реализации vector::push_back может создаваться временный объект (что вы категорически отрицаете) и для него вызываться деструктор, который всё портит. Я не виню за это программистов Microsoft, это их дело как писать свои процедуры.
И писать надо не как умею, а как того требуют правила языка. Не стыдно быть чайником - стыдно им оставаться.
Почему-то мне, кажется, что изучать новые средства лучше на простеньких программках. Т.к. в нормальных возможны большие проблемы с отладкой, из-за чего получается «кривой» код (т.к. переписывать с нуля влом).
[hr]
Да похоже программисты Microsoft что-то с STL перемудрили и действительно где-то у них создаётся временный объект. Хотя это мне кажется странным, т.к. для больших объектов из-за этого скорость должна сильно упасть!!!!!!
Уважаемый, MS тут не причем. STL он и в Африке STL.
Кажется, Вы меня не правильно поняли. Я не скидываю свою вину по написанию неправильного кода на программистов MS. Пусть пишут как хотят, как умеют, и как думают они (не я). Да у меня был баг и я его поправил.
Интересует меня другое. Я ведь всегда думал, что STL разрабатывалась/писалась так, чтобы обеспечивать максимальное быстродействие. Только вот зачем нужно создавать временный объект? (конечно, программистам MS виднее, но разработчики библиотеки, поставляемой с g++ 3.4.4, обошлись же без этого). И это, имхо, создание временного объекта может отнимать уйму времени (если этот объект очень большой). Не зря же объекты передаются по ссылке ?!

alexey_ma
30.01.2006, 22:54
Crazy_kettle:
Если запретить, то имхо в вектор ничего нельзя будет добавить :(. Кстати, Имхо вызов конструктора не вредит. Другое дело деструктор, но его я убрал :). Память освобождается при очистке вектора.
Ну вы, блин даете. Это совсем плохо. Поробуйте одну и ту-же структуру дважды в вектор добавить. A? Как тогда будет память освобождаться?

Crazy_kettle:
Да при окончании программы вызывается деструктор для строки. Но т.к. s.str==NULL, то ф-ция free(s.str) НИЧЕГО не делает, а, значит, можно считать, что для структуры s деструктор вовсе отсутствует :).
Не предусмотрел я то, что при реализации vector::push_back может создаваться временный объект (что вы категорически отрицаете) и для него вызываться деструктор, который всё портит. Я не виню за это программистов Microsoft, это их дело как писать свои процедуры.
Цитата:
Да елы-палы. Нет там никакого временного объекта. Я же привел прототип push_back. push_back В ПАРАМЕТРЕ ПОЛУЧАЕТ КОСТАНТНУЮ ССЫЛКУ(РЕФЕРЕНС)

void push_back(
const Type& _Val
);

Уважаемый, вы в курсе что такое ссылка он же референс?
Eще раз : Cоздается два объекта, один обьявленная вами локальная структура и ее копия в векторе. Оба этих объекта из-за отсутствия конструктора копирования имеют указатель char* str содержащий один и тот же адрес (это легко проверить в дебагире). Локальная структура уничтожается когда она выходит из скопа. Для неё вызывается деструктор в котором освобождается указатель str. Копия этой структуры уничтожается тогда когда вектор выходит из скопа. Вектор при удалении вызывает деструкторы для хранящихся в нём объектов. Следовательно деструктор копии пытается тоже освободить указатель str. Поскольку адрес хранящийся в этом указателе уже освобожден после вызова деструктора локальной структуры то происходит нарушение защиты памяти, в просторечии креш.
Если вы мне не верите то спросите любого програмиста хотя бы немного разбирающегося в С++ , он вам скажет то-же самое. А еще лучше, до того как начинаете писать код почитайте соответствующую литературу и ознакомтесь, наконец, с документацией на STL.

PSyton
31.01.2006, 07:04
Интересует меня другое. Я ведь всегда думал, что STL разрабатывалась/писалась так, чтобы обеспечивать максимальное быстродействие. Только вот зачем нужно создавать временный объект? (конечно, программистам MS виднее, но разработчики библиотеки, поставляемой с g++ 3.4.4, обошлись же без этого). И это, имхо, создание временного объекта может отнимать уйму времени (если этот объект очень большой). Не зря же объекты передаются по ссылке ?!
Да ну? А насколько я помню, STL разрабатывался как средство, позволяющее быстро разрабатывать программные продукты, не тратя времени на написание своих контейнеров, списков и т.п. Там же, умный дядька Бьерн Страуструп писал, что, увы это имеет свои минусы, так как в некоторых случаях снижает быстродействие за счет универсализации.
Да и что значит "я потеряю в скорости"? Все относительно... Если у тебя 100 объектов, то ты можешь начихать на это, поскольку при современных скоростях это тьфу. К тому же при написании больших проектов, далеко не все упирается в скорость, но также еще и в возможность поддежки и расширения. Таким образом, написак конструктор копирования и оператор присваивания для класса 1 раз ты можешь забыть об этолм и без оглядки на всякие там особенности писать новый код с использованием объектов этого класса. На то он и C++ и ООП в частности - никто снаружи не должен заботится о выделеии/перевыделении/очистке памяти под твою внутреннюю строку.
А почему бы не использовать std::string вместо этой убогой структуры?

Drakosha
31.01.2006, 09:50
alexey_ma:
Уважаемый, вы в курсе что такое ссылка он же референс?
Eще раз : Cоздается два объекта, один обьявленная вами локальная структура и ее копия в векторе. Оба этих объекта из-за отсутствия конструктора копирования имеют указатель char* str содержащий один и тот же адрес (это легко проверить в дебагире). Локальная структура уничтожается когда она выходит из скопа. Для неё вызывается деструктор в котором освобождается указатель str. Копия этой структуры уничтожается тогда когда вектор выходит из скопа. Вектор при удалении вызывает деструкторы для хранящихся в нём объектов. Следовательно деструктор копии пытается тоже освободить указатель str. Поскольку адрес хранящийся в этом указателе уже освобожден после вызова деструктора локальной структуры то происходит нарушение защиты памяти, в просторечии креш.

1. Насчет того что наго писать copy constructor - это конечно правильно. 100% согласен
2. В данном случае объект не выходит из скопа до печати на экран. Как вы обясните поведение этой программы а не теоретическое поведение STL (которое вы объясняете совершенно правильно). Я вижу только одно объяснение - где-то временный объект таки создаётся. Кроме как в коде STL я для этого мест не вижу.

alexey_ma
31.01.2006, 11:47
Drakosha:
2. В данном случае объект не выходит из скопа до печати на экран. Как вы обясните поведение этой программы а не теоретическое поведение STL (которое вы объясняете совершенно правильно). Я вижу только одно объяснение - где-то временный объект таки создаётся. Кроме как в коде STL я для этого мест не вижу.
Ok. Понял что вас смущает. То что есть вызов деструктора до того как все объекты выходят из скопа. Для это нужно посмотреть реализацию функции вектора _Insert_n

void _Insert_n(iterator _Where,
size_type _Count, const _Ty& _Val)
{ // insert _Count * _Val at _Where
_Ty _Tmp = _Val; // in case _Val is in sequence
size_type _Capacity = capacity();

if (_Count == 0)
;
else if (max_size() - size() < _Count)
_Xlen(); // result too long
else if (_Capacity < size() + _Count)
{ // not enough room, reallocate
_Capacity = max_size() - _Capacity / 2 < _Capacity
? 0 : _Capacity + _Capacity / 2; // try to grow by 50%
if (_Capacity < size() + _Count)
_Capacity = size() + _Count;
pointer _Newvec = this->_Alval.allocate(_Capacity);
pointer _Ptr = _Newvec;

_TRY_BEGIN
_Ptr = _Ucopy(_Myfirst, _ITER_BASE(_Where),
_Newvec); // copy prefix
_Ptr = _Ufill(_Ptr, _Count, _Tmp); // add new stuff
_Ucopy(_ITER_BASE(_Where), _Mylast, _Ptr); // copy suffix
_CATCH_ALL
_Destroy(_Newvec, _Ptr);
this->_Alval.deallocate(_Newvec, _Capacity);
_RERAISE;
_CATCH_END

_Count += size();
if (_Myfirst != 0)
{ // destroy and deallocate old array
_Destroy(_Myfirst, _Mylast);
this->_Alval.deallocate(_Myfirst, _Myend - _Myfirst);
}
_Myend = _Newvec + _Capacity;
_Mylast = _Newvec + _Count;
_Myfirst = _Newvec;
}
else if ((size_type)(_Mylast - _ITER_BASE(_Where)) < _Count)
{ // new stuff spills off end
_Ucopy(_ITER_BASE(_Where), _Mylast,
_ITER_BASE(_Where) + _Count); // copy suffix

_TRY_BEGIN
_Ufill(_Mylast, _Count - (_Mylast - _ITER_BASE(_Where)),
_Tmp); // insert new stuff off end
_CATCH_ALL
_Destroy(_ITER_BASE(_Where) + _Count, _Mylast + _Count);
_RERAISE;
_CATCH_END

_Mylast += _Count;
fill(_ITER_BASE(_Where), _Mylast - _Count,
_Tmp); // insert up to old end
}
else
{ // new stuff can all be assigned
pointer _Oldend = _Mylast;
_Mylast = _Ucopy(_Oldend - _Count, _Oldend,
_Mylast); // copy suffix
copy_backward(_ITER_BASE(_Where), _Oldend - _Count,
_Oldend); // copy hole
fill(_ITER_BASE(_Where), _ITER_BASE(_Where) + _Count,
_Tmp); // insert into hole
}
}


Там где жирным виделено происходит копирование объекта в локальный объект _Tmp. Его деструктор вам и мешает. Поэтому в вашей программе деструктор будет вызыватся три раза а не два. Причем первый раз до выхода объектов из скопа сразу после строки vec.push_back(s);

Drakosha
31.01.2006, 17:03
:claps: ну вот, все согласны :beer:
радует что в g++ STL сделанно лучше

Crazy_kettle
31.01.2006, 23:03
alexey_ma вы наверное очень умный, но, имхо, это не значит, что это даёт Вам право [внимательно\вовсе] НЕ читать посты других участников.

Локальная структура уничтожается когда она выходит из скопа. Для неё вызывается деструктор в котором освобождается указатель str.
Во первых, вы уже сами поняли, что лок. переменная до возникновения неправильного вывода из скопа не выходила, но об этом написано начиная с первого поста:
ведь переменная s и вектор vec ещё используются (не говоря уже об области видимости)
Писалось также, что я специально принял меры, чтобы избежать "пагубного" влияния вызова деструктора для переменной s. В первом посте (в виде комментария) и в посте http://www.imho.ws/showpost.php?p=1119412&postcount=8:
Да при окончании программы вызывается деструктор для строки. Но т.к. s.str==NULL, то ф-ция free(s.str) НИЧЕГО не делает, а, значит, можно считать, что для структуры s деструктор вовсе отсутствует
Я понимаю, что это решения может быть галимым, но тогда нужно, имхо, это решение и обсуждать, а не говорить то, что мне и так понятно (хотя Вы мне в этом не верите :( ).
Это так было сказано к слову и не значит, что я горю расжигать перебранку. :beer:

STL разрабатывалась/писалась так, чтобы обеспечивать максимальное быстродействие.
Да ну?

От стандартной библиотеки не просто требуется выполнять свои задачи, она также должна выполнять их достаточно эффективно, чтобы у пользователя не позникло соблазна использовать совственные механизмы. (Страуструп. Язык С++. 2002 год. стр. 487). И ещё где-то он писал, что перед тем, чтобы думать, что ваше средство эффективнее стандартного, проведите широкомаштабное исследование.
Если у тебя 100 объектов, то ты можешь начихать на это, поскольку при современных скоростях это тьфу. К тому же при написании больших проектов, далеко не все упирается в скорость, но также еще и в возможность поддежки и расширения.
С одной стороны Вы правы, но с другой, хочется, уже сейчас заботится об эффективности. Более того, что я писал не большой проект, а прогу для себя (хоть и не маленькую). И мне хотелось её побыстрее склепать.
А почему бы не использовать std::string вместо этой убогой структуры?
В данном примере Вы несомненно правы. Но здесь приведён не кусок того исходного кода :) (было выловлено место ошибки и написан специально под неё пример). Конечно, в программе можно было заменить все char* на string, но это решено было не делать по следующим причинам:
1) (уже писалось почему) Решено было использовать стандартную библиотеку С и WinAPi для работы с файлами и каждый раз конвертить string в char* надоело бы, да и неизвестно мне насколько это эффективно
2) Нельзя использовать string::c_str() для изменения, что доставляло бы хлопот при работе с нек. функциями, например с fwrite.
3) В этом случае возможны ненужные выделения памяти

alexey_ma
01.02.2006, 10:26
Crazy_kettle:
Я понимаю, что это решения может быть галимым, но тогда нужно, имхо, это решение и обсуждать, а не говорить то, что мне и так понятно (хотя Вы мне в этом не верите :( ).
Давайте обсудим решение.
Я же привел вам нормальное ( относительно конечно , я бы все равно так бы не писал) решение в третьем посте, с нормальным конструктором и с нормальным использованием вектора. Чем оно не понравилось ? Ваше решение изначально кривое, вы не правильно работаете с вектором и последствия этой неправильной работы пытаетесь заткнуть с помощью всяких ухищрений при этом обвиняя STL в плохой реализации. Еще раз настоятельно советую почитать документацию по STL. Возможно даже сможете вместо fwrite использовать стримы STL. :)
Crazy_kettle:
Решено было использовать стандартную библиотеку С и WinAPi для работы с файлами и каждый раз конвертить string в char* надоело бы, да и неизвестно мне насколько это эффективно

Вы еще даже не знаете насколько это эффективно или нет а уже пытаетесь бороться с неэффективностью посредством кривого кода. Почему - бы сначала не проверить? Возможно, не придеться изобретать велосипед.
Посчему бы не использовать STL для работы с файлам вместо WinAPi?

Drakosha:
радует что в g++ STL сделанно лучше

Если не влом, приаттачте vector.h из gcc.Любопытно, насколько они отличаются.

PSyton
01.02.2006, 11:32
Если не влом, приаттачте vector.h из gcc.Любопытно, насколько они отличаются.
Пожалуйста, только по моему одного вектора будет мало...
Ну да ладно.

alexey_ma
01.02.2006, 12:47
Да. Ничего общего.

Crazy_kettle
02.02.2006, 01:20
to alexey_ma
Такое ощущение, что мы говорим на разных языках.
Давайте обсудим решение.
Я же привел вам нормальное ( относительно конечно , я бы все равно так бы не писал) решение в третьем посте, с нормальным конструктором и с нормальным использованием вектора. Чем оно не понравилось ?
Здесь имелось ввиду (что, кажется мне очевидным, читая пост http://www.imho.ws/showpost.php?p=1120117&postcount=14) моё бывшее решение проблемы вызова деструктора для структуры и для элемента вектора :
s.str=0;//Чтобы деструктор не пытался освободить память повторно.. Т.е. обсудить эту строчку, порождённые ей проблемы (ту, что она не решает проблему вызова деструктора во временном объекте я знаю, если будут другие мысли то пишите), а не говорить мне постоянно про существование деструкторов и всякие там кросс-референсы. Особенно, учитывая, что я ПИСАЛ, что как-раз эту проблему я учитывал и пытался решать.
Что насчёт вашего решения, то она мне не понравилось из-за ТРЁХ НЕ нужных выделений и освобождений памяти. К тому же ваше решение "педалится", если строка содержит символ '\0' (конечно, со string это не проблема и Ваш вариант можно немного модифицировать, но это так к слову)
вы не правильно работаете с вектором и последствия этой неправильной работы пытаетесь заткнуть с помощью всяких ухищрений при этом обвиняя STL в плохой реализации
Прочитайте, пожалуйста, пост http://www.imho.ws/showpost.php?p=1119412&postcount=8 после цитаты поста PSyton. Там, вроде, понятно написано, что я не виню программистов MS за мой "кривой" код с багом. А только говорю, что это развеяло моё представление, что STL (STL от MS ;) ) разрабатывается так, чтобы обеспечить максимально-возможное быстродействие.
Посчему бы не использовать STL для работы с файлам вместо WinAPi?
Я просто не знаю так средствами STL вывести все файлы папки по маске, прочитать/изменить права/аттрибуты. Если это можно, по пишите.
[hr]

И вообще alexey_ma я считаю, что не нужно развивать эту тему :beer:.
Я знаю, что мой код "кривой". Но также знаю, что этот код писался для меня и врядли будет сопровождаться и маштабироваться :).
Более того, я понял, что малой кровью от "кривизны" (в моём понимании) не избавиться. Поэтому, возможно, в будущем всё перепишется, когда больше прокачаюсь. А сейчас я не вижу лезть в код, кот., вроде, прекрасно пока работает.