2015-06-25 1 views
0

Это, вероятно, дубликат, но предположим, что мы следующий кодкак функция/метод возвращает ссылку на объект внутри работы

#include <stdio.h> 
#include <stdlib.h> 

class IPair{ 
public: 
    IPair(const char *s) : s(s){ 
     buffer = malloc(1024); 
    }; 

    virtual ~IPair(){ 
     free(buffer); 
    } 

    virtual void print() const = 0; 

    const char *s; 
    void *buffer; 
}; 

class Pair : virtual public IPair{ 
public: 
    Pair(const char *s) : IPair(s){}; 

    virtual void print() const override{ 
     printf("Hello %s\n", s); 
    } 
}; 

Pair createPair(const char *s){ 
    return Pair(s); 
} 

IPair & usePair(IPair &pair){ 
    pair.print(); 

    return pair; 
} 

int main(int argc, char** argv) 
{ 
    Pair a = createPair("AAA"); 
    Pair b = createPair("BBB"); 

    usePair(a); 
    IPair &x = usePair(b); 
    usePair(x); 

    return 0; 
} 

Если рассмотрение с Valgrind, нет утечки памяти - например, деструктор называется правильным «местом».

Это увеличило следующие вопросы:

  1. что именно происходит внутри createPair()? Похоже, память объекта копируется. Является ли memcpy() похожим или что-то делать с конструктором копирования?
  2. usePair() получить ссылку, а затем вернуть ту же ссылку назад. поскольку указанный объект все еще находится в основном() объеме, это должно быть safe операция - это предположение верно?
+0

Любые причины использования malloc, а не новых или умных указателей? – Marcin

+0

это утечка памяти. нет особой причины – Nick

ответ

3
  1. Как конструктор копирования - если не конструктор не указан, то компилятор будет сделать один, который по существу memcpy(*this, rhs, sizeof(*this));. Оптимизация возвращаемого значения, которая заключается в том, что компилятор передает адрес адресата, чтобы сохранить значение в - удаление необходимости в копии в большинстве случаев. [На самом деле, все возвраты структуры/класса будут изменять вызов таким образом, чтобы компилятор передавал объект, который должен быть возвращен как ссылочный параметр]

  2. Ссылки почти такие же, как указатели на C++, поэтому, когда вы возвращаете ссылку, адрес объекта возвращается. Разница в том, что ссылки не нужны оператору разыменования и могут быть назначены только один раз.

+1

На самом деле созданный компилятор экземпляр копии копирует элементы по значению - включая вызовы конструкторов копий членов, которые их имеют. Кроме того, реализация RVO и/или превращение структуры по значению в структуру по ссылке зависит от компилятора - не все компиляторы делают такие вещи. – Peter

3
  1. В создании пары объект строится, а затем возвращается. Это включает конструктор копирования (можно избежать, если Pair реализует конструктор Move). Кроме того, RVO (оптимизация возвращаемого значения) может помочь избежать ненужного копирования)
  2. usePair обрабатывает ссылки и здесь не происходит копирования. Все в порядке.

P.S. Объявить деструктор IPair виртуального ...

+1

не виртуальный dtor - это опечатка, исправлена ​​ – Nick

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