Выделение места для возвращенной ссылки - PullRequest
1 голос
/ 05 марта 2012

Я создал функцию для вычисления разности двух временных функций. Вот базовая версия этой функции.

struct timeval* getDifference(struct timeval* startTime, struct timeval* finishTime)
{
    struct timeval* difference = new struct timeval;
    difference->tv_sec = finishTime->tv_sec - startTime->tv_sec;
    difference->tv_usec = finishTime->tv_usec - startTime->tv_usec;
    return difference;
}

int main()
{
    struct timeval a,b;
    struct timeval* c;
    gettimeofday(&a, NULL);
    usleep(100000);
    gettimeofday(&b, NULL);

    c = getDifference(&a, &b);
 }

Что я хочу знать, если использование struct timeval* c; безопасно? или это должно быть похоже на struct timeval* c = new struct timeval;?

Если это безопасно, освобождает ли c освобождение difference = new struct timeval;, выделенного внутри функции?

Ответы [ 5 ]

3 голосов
/ 05 марта 2012

Я бы предложил вообще не использовать указатели в вашем случае. Пусть аргументы будут ссылками, которые будут скопированы с возврата:

struct timeval getDifference(const struct timeval& startTime, const struct timeval& finishTime)
{
    struct timeval difference;
    difference.tv_sec = finishTime.tv_sec - startTime.tv_sec;
    difference.tv_usec = finishTime.tv_usec - startTime.tv_usec;
    return difference;
}
1 голос
/ 05 марта 2012

Это безопасно (в данном случае) и да, это освободит память, выделенную на getDifference (если вы на самом деле вызовете delete).

Однако вы должны привыкнуть к инициализации ваших указателей наNULL - если вы не можете инициализировать их каким-либо другим значением.Например, в следующем случае поведение не определено:

struct timeval a,b;
struct timeval* c;
gettimeofday(&a, NULL);
usleep(100000);
gettimeofday(&b, NULL);
if ( someCondition )
    c = getDifference(&a, &b);
delete c;

Если someCondition равно false, вы удаляете c, который не был правильно инициализирован.Если он был инициализирован в NULL, поведение хорошо определено (оно ничего не делает).

0 голосов
/ 05 марта 2012

Да, это безопасно, но, как правило, вы хотите избежать выделения памяти в функции и освободить () ее в другой.

Я бы предложил изменить прототип нашей функции getDifference, чтобы получить указатель на разницу во времени:

int getDifference(struct timeval* startTime, struct timeval* finishTime, 
                  struct timeval *difference)

Теперь вы можете сделать так, чтобы ваш главный поступок был таким:

int getDifference(struct timeval* startTime, struct timeval* finishTime, struct timeval *difference)
{
    if( difference && startTime && finishTime) {
        difference->tv_sec = finishTime->tv_sec - startTime->tv_sec;
        difference->tv_usec = finishTime->tv_usec - startTime->tv_usec;
        return 0;
    }
    return -1;
}

int main()
{
    struct timeval a,b;
    struct timeval c;
    gettimeofday(&a, NULL);
    usleep(100000);
    gettimeofday(&b, NULL);

    if( getDifference(&a, &b, &c) == 0 )
    { 
        // success !!
    }
 }
0 голосов
/ 05 марта 2012

Было бы бессмысленно и даже вредно вызывать struct timeval* c = new struct timeval; перед вызовом c = getDifference(...);, потому что вызов new выделяет память, которая затем будет потеряна при перемещении указателя c на возвращаемое значение getDifference.

Однако, поскольку getDifference() распределяет свое возвращаемое значение, вызывающий оператор (функция main) должен освободить память.Так что да, вы должны позвонить delete на возвращаемое значение getDifference.

0 голосов
/ 05 марта 2012

Да, это безопасно, потому что вы возвращаете указатель на уже распределенную структуру.И да, освобождение c освободит структуру, которую вы разместили в функции.Кстати, возможно, лучшим выбором будет размещение структуры вне функции, а затем передача указателя на нее, потому что вам не нужно думать о том, кто ее выделил и кто отвечает за освобождение.

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