C ++ new & delete, строка и функции - PullRequest
6 голосов
/ 03 июня 2010

Хорошо, на предыдущий вопрос был дан четкий ответ, но я обнаружил еще одну проблему.

Что если я сделаю:

char *test(int ran){ 
    char *ret = new char[ran]; 
    // process... 
    return ret; 
} 

А затем запустите его:

for(int i = 0; i < 100000000; i++){ 
   string str = test(rand()%10000000+10000000); 
   // process... 

   // no need to delete str anymore? string destructor does it for me here?
} 

Так что после преобразования символа * в строку мне больше не нужно беспокоиться об удалении?

Редактировать: В ответ я должен delete[] каждый вызов new[], но в моем случае это невозможно, так как указатель потерян, поэтому возникает вопрос: как преобразовать char в Строка правильно?

Ответы [ 5 ]

9 голосов
/ 03 июня 2010

Здесь вы не конвертируете char* в [std::]string, а копируете char* в [std::]string.

Как правило, для каждого new должно быть delete.

В этом случае вам нужно сохранить копию указателя и delete, когда вы закончите:

char* temp = test(rand()%10000000+10000000);
string str = temp;
delete[] temp;
3 голосов
/ 03 июня 2010

Вы, похоже, находитесь под впечатлением, что передача char* в std :: string передает владение выделенной памятью.Фактически он просто делает копию.

Самый простой способ решить эту проблему - просто использовать std :: string во всей функции и возвращать ее напрямую.

std::string test(int ran){ 
    std::string ret;
    ret.resize(ran - 1);  // If accessing by individual character, or not if using the entire string at once.
    // process... (omit adding the null terminator)
    return ret; 
} 
2 голосов
/ 04 июня 2010

Вам нужно сделать что-то вроде этого:

for(int i = 0; i < 100000000; i++){ 
   int length = rand()%10000000+10000000;
   char* tmp = test(length); 
   string str(tmp);
   delete[length] tmp;
}

Это удаляет выделенный массив символов должным образом.

Кстати, вы всегда должны завершать строку нулем, если вы создаете ее таким образом (т.е. внутри функции test), в противном случае некоторые функции могут легко запутаться и трактовать данные за вашей строкой как ее часть. , что в лучшем случае приводит к сбою в работе вашего приложения, а в худшем случае создает тихое переполнение буфера, приводящее к неопределенному поведению на более позднем этапе, что является окончательным кошмаром отладки ...;)

2 голосов
/ 03 июня 2010

Вы должны вызывать delete для каждого new, иначе вы потеряете память. В случае, если вы показали, что вы выбрасываете указатель, если вы должны оставить функцию, возвращающую char*, вам потребуется использовать две строки для создания std::string, чтобы вы могли сохранить копию char* до delete.

Лучшим решением было бы переписать вашу функцию test(), чтобы она возвращала std::string напрямую.

2 голосов
/ 03 июня 2010

Да, да, вы делаете.

Если вы используете Linux / OS X, посмотрите на что-то вроде valgrind , которое может помочь вам с проблемами памяти

Вы можете изменить свою тестовую функцию, чтобы она возвращала string вместо char *, таким образом вы можете delete [] ret в тестовой функции.

ИЛИ вы также можете просто использовать строку в тесте и не беспокоиться о новой / удалить.

...