2010-06-03 3 views
6

У меня вопрос previous. Ответ на вопрос был дан однозначно, но я обнаружил еще одну проблему.C++ new & delete and 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[] вызов, но в моем случае его не представляется возможным, так как указатель потерялся, поэтому возникает вопрос: как преобразовать символ в строку правильно?

+0

Re: Edit ... Или don 't потерять указатель (согласно моему ответу ниже) или (еще лучше) не 'new' указатель, просто используйте' std :: string', чтобы удерживать строку. Почему вы хотите сами распределить память? – Johnsyweb

ответ

9

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

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

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

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

Итак, как правильно преобразовать символ в строку? – Newbie

+0

Я думаю, когда вам сказали преобразовать 'char *' в 'std :: string', что означало, что вы должны ** использовать **' std :: string', а не 'char *', а не * конвертировать * программно. – Johnsyweb

+0

Может ли быть более простой способ сделать это? как какая-то функция или что-то в этом роде, так что потребуется всего одна строка кода? – Newbie

2

Да, да.

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

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

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

+0

Так что я должен использовать: delete [] str; ? – Newbie

+0

Нет, str - это собственный объект. В этом случае вы потеряли указатель на новый char [], который вы выделили, и, следовательно, будете иметь утечку памяти, так как вы не можете удалить его. –

3

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

Самый простой способ решить эту проблему - просто использовать 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; 
} 
+0

+1 для пропуска промежуточного шага создания символа char *. Тем не менее, в вашем примере кода отсутствует имя ... –

2

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

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

2

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

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

Это удаляет выделенный обугленного-массив правильно.

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