Переменная int * или переменная int - PullRequest
2 голосов
/ 05 октября 2011

Я работаю в C ++ и в последнее время много использую указатели. Я обнаружил, что есть несколько способов инициализации фрагментов памяти, которые мне нужно использовать.

void functioncall(int* i)
{
    *i = *i + 1;
}

int main(){
    int* a = (int*)malloc(sizeof(int));
    int az = 0;

    functioncall(a);
    functioncall(&az);
}

Обратите внимание, что первая переменная int * a объявлена ​​как указатель, а затем я выделяю память для нее. Но с az это не указатель, а при вызове функции я получаю адрес памяти.

Итак, мой вопрос: есть ли предпочтительный путь = или есть какие-то штрафы один над другим?

Ответы [ 8 ]

7 голосов
/ 05 октября 2011
int* a = (int*)malloc(sizeof(int));

Это выделяет память в куче. Вы должны освободить его самостоятельно, иначе вы столкнетесь с утечками памяти. Вы освобождаете это, звоня free(a);. Эта опция определенно медленнее (так как память должна быть запрошена, а некоторые другие фоновые операции должны быть выполнены), но память может быть доступна, пока вы звоните бесплатно.


int az = 0;

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

3 голосов
/ 05 октября 2011

a помещается в кучу, az находится в стеке.Куча, которую вы несете ответственность за освобождение памяти.Когда стек выходит из области видимости, он автоматически освобождается.Таким образом, ответ заключается в том, когда вы хотите, чтобы данные были размещены, и если вам нужно, если в конце области.

PS Вы должны использовать новый в C ++

1 голос
/ 05 октября 2011

Я не уверен, что вы пытаетесь сделать, но почти никогда нет причин выделять один int (или массив int, если на то пошло).И в вашем functioncall есть как минимум две ошибки: во-первых, он не может проверить нулевой указатель (если указатель не может быть нулевым, передается по ссылке), а во-вторых, он ничего не делает: он увеличиваеткопия указателя, переданная в качестве аргумента, затем разыменовывает начальное значение и выбрасывает прочитанное значение.

1 голос
/ 05 октября 2011

Как правило, следует избегать динамического выделения памяти (malloc, calloc, new), когда это достаточно просто: они медленнее, чем выделения стека, но, что более важно, вы должны помнить, чтобы освободить (free, delete) вручную память, полученная при динамическом выделении, в противном случае у вас возникают утечки памяти (как это происходит в вашем коде).

0 голосов
/ 05 октября 2011

func (typename * p)

указатель является значением вызова

* p ++ is * p и p ++

если изменить этот указатель, а не изменить оригинал.

0 голосов
/ 05 октября 2011
int az = 0;
functioncall(a);

Это нормально, что касается поведения.

int* a = (int*)malloc(sizeof(int));
functioncall(&az);

Это вызывает неопределенное поведение (UB) внутри функции, когда вы делаете *i++.Поскольку malloc только выделяет память, она не инициализирует ее.Это означает, что *i все еще неинициализирован, и чтение неинициализированной памяти вызывает UB;это объясняет, почему *i++ является UB.А UB, если вы знаете, самая опасная вещь в C ++, потому что это означает, что может произойти все что угодно.

Что касается первоначального вопроса, что бы вы предпочли?Таким образом, ответ таков: предпочитайте автоматическую переменную вместо указатель (будет ли он выделен с malloc или new).

Автоматически означает Быстро, Чисто и Безопасно.

0 голосов
/ 05 октября 2011

Первая строка (int * a = ...) называется динамически распределяемой переменной, она обычно используется, если вы не знаете до времени выполнения, сколько переменных вам нужно, или если вам это нужно вообще.

Вторая строка (int az = 0) называется автоматической переменной, она используется более регулярно.

0 голосов
/ 05 октября 2011

Выделение небольших переменных непосредственно в стеке обычно происходит быстрее, поскольку вам не нужно выполнять никаких операций с кучей.Также меньше шансов на провалы, связанные с указателями (например, двойные освобождения).Наконец, вы используете меньше места.Помимо кучи накладных расходов, вы все еще перемещаете указатель и целое число вокруг.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...