C++ new & delete и string & functions


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

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

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?
} 

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

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

5 6

5 ответов:

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

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

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

char* temp = test(rand()%10000000+10000000);
string str = temp;
delete[] temp;

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

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

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; 
} 

Да, да, это так.

Если вы используете linux / os x, посмотрите на что-то вроде valgrind , что может помочь вам с проблемами памяти

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

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

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

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

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

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

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

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