2015-05-21 3 views
1

У меня есть рабочий код для функции, которая принимает символ и число и формирует строку, дублируя этот символ столько раз. Вот часть, которая прекрасно работает.Запрос инкремента указателя на C++

char * buildstr(char c, int n) 
{ 
    char * pc = new char[n+1]; 
    for (int i = 0; i < n; ++i) 
    { 
     *(pc+i) = c; 
    } 

    *(pc+n) = '\0'; 
    return pc; 
} 

Но если я использую другую логику, где я непосредственно увеличиваем сам указатель непосредственно после этого я получаю ошибку, когда я освободить память в основной функции с помощью удаления [].

Что может быть моей проблемой?

Спасибо,

char * buildstr(char c, int n) 
{ 
    char * pc = new char[n+1]; 
    for (int i = 0; i < n; ++i) 
    { 
     *pc = c; 
     pc++; 

    } 
    *(pc) = '\0'; 
    return pc; 
} 
+2

Вы возвращаете инкрементный указатель, а не тот, который возвращается из распределения. Кроме того, вместо выражений типа '* (pc + i)' вы должны использовать эквивалентный и более читаемый 'pc [i]'. –

+2

Это не должно быть помечено как C, это явно C++. – unwind

+1

Обратите внимание, что нет необходимости писать такую ​​функцию в C++ (за исключением, возможно, для обучения), поскольку 'std :: string' [имеет конструктор (см. (2))] (http: //en.cppreference.com/w/cpp/string/basic_string/basic_string), который делает именно это (и еще один большой плюс: он управляет памятью для вас). –

ответ

2

Во втором примере вы увеличиваете значение указателя. Когда вы пытаетесь удалить его, он указывает на последнюю позицию массива.

Таким образом, когда вы вызываете его delete[], он падает, ожидая pc, чтобы указать на адрес, который изначально был выделен с использованием new[].

Я рекомендую вам использовать первый подход, так как вы сможете отслеживать базовый адрес в течение срока службы pc. Более того, я думаю, вам будет проще сделать это, используя нотацию массива.

Рассмотрите возможность использования:

pc[i] = c; 

вместо

*(pc+i) = c; 

Как это более идиоматических и легко читать. Если вы просто выполняете свою арифметику указателя, придерживайтесь первого подхода, который вы описали.

+0

Спасибо. Я знаком с записью массива и что вторая функция is'nt хороший способ реализовать эту вещь. Но я делал это для обучения, и у меня есть важная концепция, которая удаляет [] ожидает, что тот же адрес будет присвоен новому. Я этого не знал. Спасибо всем за помощь. – jav321

7

Проблема заключается в том, что вы возвращая указатель инкрементируется. delete[] должен быть вызван со значением указателя, которое было возвращено вызовом new[], иначе вы получите неопределенное поведение. То же самое касается звонков free и указателей, возвращаемых malloc, calloc и т. Д.

+0

Иногда это немного сложно понять, где именно заблуждение ПП. Это на самом деле классический пример. Я собирался спросить OP в комментарии, если он/она серьезно относился к тому, чтобы не видеть проблему, но затем я осознал, что его восприятие блока памяти является некоторой мягкой «атомной единицей». Возможно, вы должны прояснить эту проблему в своем ответе, потому что я думаю, что именно здесь происходит путаница OP (см. Мой комментарий к вопросу). –

0

В первой функции предположим, что ваш указатель начинается с 0x00100. , когда вы делаете петлю вы получите к следующему адресу так для Exemple скажем 4 цикла:

0x00100 
0x00101 
0x00102 
0x00103 

, но в конце концов вы вернуть указатель на 0x00100 beceause вы использовали индекс *(pc+i) где i является индексом, так это хорошо.

Теперь на вторую функции вы делаете то же самое, что ваш Зависят двигаются сам указатель без индекса, так что вы вернуть указатель на последний адрес

0x00103 

То есть WY вашей вторая функция не работает

Смежные вопросы