Указатели c ++, используемые как псевдомассивы. Присвоение номера нескольким последовательным позициям памяти без массива - PullRequest
0 голосов
/ 07 мая 2020

Это больше похоже на разговор c, чем на вопрос. Взгляните на следующий код для вычисления n-го числа Фибоначчи и распечатайте их все до n-го (пространство имен std задано, и следующее находится в основном):

int n=20;
int *a=new int; //notice NO size declaration
a[0]=1;
a[1]=1;
for(int i=2; i<n;i++){
    a[i]=a[i-1]+a[i-2];
}

for(int i=0; i<n;i++){
    cout<<a[i]<<endl;
}

Так должно ли это работать? Работает ли это для вас? Есть комментарии, не сработает ли это для кого-то? Заранее спасибо. Это мой личный метод динамического распределения памяти в 1D, но я не могу найти никакой документации по этому методу, и я использую его всегда. Конечно, я не делаю то же самое в 2D. Спасибо за внимание.

Ответы [ 2 ]

0 голосов
/ 07 мая 2020

То, как вы это делаете, не является «безопасным для памяти», потому что вы выделяете память только для одного целого числа и получаете доступ к последующим адресам, которые не были выделены. Это эквивалентно объявлению массива определенного размера и доступу к индексам, превышающим его размер. Есть несколько вариантов сделать то, что вы хотите:

Выделение памяти вручную

Используйте malloc(), чтобы выделить необходимое количество байтов. После его использования вы должны использовать free(). Компилятор не делает этого за вас.

int n=20;
int *a = malloc(sizeof(int) * n);
a[0]=1;
a[1]=1;
for(int i=2; i<n;i++){
    a[i]=a[i-1]+a[i-2];
}
free(a);

Использование векторного контейнера C ++

Векторы - это массивы динамического размера. Они могут изменять размер автоматически и очень полезны. Подробнее здесь .

int n=20;
std::vector<int> a;
a.push_back(1);
a.push_back(1);
for(int i=2; i<n;i++){
    a.push_back(a[i-1]+a[i-2]);
}

Редактировать: уточните, что нужно free() после использования malloc().

0 голосов
/ 07 мая 2020

Так должно работать?

Нет. Доступ к любому индексу, кроме a[0], приводит к неопределенному поведению, поскольку он находится за пределами выделенной памяти.

Это работает для вас?

Может показаться, что он работает в некоторых случаи. Когда у вас неопределенное поведение, может случиться что угодно; не требуется, чтобы ошибка была обнаружена (см. Почему я не получаю ошибку сегментации, когда я пишу за пределами конца массива? ). Возможно, память, которую он использует, не используется ни для чего другого, поэтому это не вызывает очевидного сбоя. Но это также могло вызвать повреждение данных, которые используются какой-либо несвязанной частью приложения или библиотеки; вы можете не сразу заметить проблему.

Распространенным признаком неопределенного поведения является то, что кажущиеся безобидными изменения вызывают неожиданные изменения в поведении. Например, программа может работать с оператором печати в нем, но не работать при удалении этого оператора.

...