2010-04-02 3 views
10

Правильно ли это объект, возвращаемый функцией?Возврат локального объекта из функции

Car getCar(string model, int year) { 
    Car c(model, year); 
    return c; 
} 

void displayCar(Car &car) { 
    cout << car.getModel() << ", " << car.getYear() << endl; 
} 

displayCar(getCar("Honda", 1999)); 

У меня ошибка, «с адресом временного». Должен ли я использовать этот способ:

Car &getCar(string model, int year) { 
    Car c(model, year); 
    return c; 
} 

ответ

23

getCar возвращает Car по значению, которое является правильным.

Вы не можете передать это возвращаемое значение, которое является временным объектом, в displayCar, так как displayCar принимает Car&. Вы не можете привязать временную ссылку к неконстантной ссылке. Вы должны изменить displayCar принять константную ссылку:

void displayCar(const Car& car) { } 

Или, вы можете хранить временно в локальной переменной:

Car c = getCar("Honda", 1999); 
displayCar(c); 

Но, это лучше иметь displayCar взять константную ссылку, поскольку он Безразлично Не изменяйте объект.

Не следует ссылается на местную переменную Car.

+0

вы также можете сохранить временное выражение без вызова конструктора копирования (который встречается в 'Car c = getCar (...)', используя ссылку на const: 'const Car & c = getCar (...)', если вы «Мне нужно внести изменения через' c' позже. –

4

Неверно возвращать ссылку на локальную переменную из функции.

Так что да, это правильно:

Car getCar(string model, int year) { 
    Car c(model, year); 
    return c; 
} 
+0

Хм, мне нужно что-то вроде заводской функции, которая создаст объект и вернет его обратно. – pocoa

+1

Многие (большинство?) Компиляторов оптимизируют 'return Car (model, year)', так что никакой дополнительной копии не требуется, поэтому я бы избавился от явной локальной переменной. –

+0

@Steven: Многие (большинство?) Компиляторов также реализуют именованную оптимизацию возвращаемого значения (NRVO), поэтому в целом нет никакой разницы. –

8

Ваша проблема:

void displayCar(Car &car) { 
    cout << car.getModel() << ", " << car.getYear() << endl; 
} 

следует использовать константную ссылку:

void displayCar(const Car & car) { 
    cout << car.getModel() << ", " << car.getYear() << endl; 
} 

Эта функция:

Car getCar(string model, int year) { 
    Car c(model, year); 
    return c; 
} 

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

Car getCar(const string & model, int year) { 

В общем, для типов классов, таких как string или Car, ваш выбор по умолчанию для параметра всегда должен быть ссылкой на константу.

0

Еще лучше:

Car getCar(string model, int year) { 
     return Car(model, year); 
} 
+0

То, что я имел в виду под «копированием» в моем ответе. Хотя в настоящее время это стандартное решение, это гораздо более дорогостоящая операция, чем просто возврат адреса. – themoondothshine

+1

@themoondothshine : Большинство компиляторов (все, что я знаю) будет выполнять RVO здесь, так что это действительно дешевая операция. –

2

Да, это, безусловно, не безопасно возвращать ссылку или указатель на временный объект. Когда он истечет (т.е. когда выйдет функция getCar), вы останетесь с тем, что известно как «обвисший указатель».

Однако, если вы заинтересованы в сокращении операций копирования на объекте, вы должны проверить C++ 0x «Переместить семантику». Это относительно новая концепция, но я уверен, что она скоро станет основным потоком. GCC 4.4 поддерживает C++ 0x (используйте параметр компилятора -std=c++0x для включения).

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