2013-04-12 5 views
1

Я прочитал этот вопрос «Why doesn't C++ support functions returning arrays?». Говорят, что когда мы пытаемся получить доступ к массиву извне этой функции (через возвращаемое значение), у нас есть проблема, потому что мы пытаемся получить доступ к памяти, которая не входит в область действия, с которой вы работаете (стек вызова функции).Функция C++ возвращает вектор/строку, но не массив

Не возникает такая же проблема, когда мы возвращаем std :: string или std :: vector, который объявлен внутри функции, или C++ создает копию строки или вектора и возвращает копию вызывающей стороне, чтобы строка или вектор не выходит за рамки.

vector<int> foo(const vector<int> a) 
{ 
    vector<int> b = a; 
    return b; 
} 

int main() 
{ 
    vector<int> a; 
    vector<int> c = foo(a); 
} 
+2

'vector b' from' foo (...) 'будет скопирован в' c'. После выполнения 'a' и' c' будут копиями одного и того же объекта. – lcs

+0

ahem ... ** 'int' ** main ... –

+0

Спасибо, отредактирован до int main – Raghav

ответ

2

Он делает копию объекта std :: vector. Память, которую std :: vector использует для хранения своих данных, выделяется в куче (и которая также копируется).

(Некоторые оптимизации компилятора означают копии не всегда бывает, за кулисами, например, в примере кода, я думаю, что большинство компиляторов будет копировать из a в b, внутри foo(), но b станет c в main() скорее чем быть скопированы снова)

дополнительная литература:. http://en.wikipedia.org/wiki/Copy_elision и http://en.wikipedia.org/wiki/Return_value_optimization (спасибо millsj за предложение) пункт 20 более эффективного C++, Скотт Мейерс, также покрывает это.

2

Да, в вашем примере он вызовет конструктор копирования, чтобы сделать копию, оригинальная копия выйдет за пределы области видимости, но возвращенная копия не будет использоваться и не может использоваться для выполнения операций над ней, таких как присвоение другие объекты внутри main. Поскольку в настоящее время компиляторы действительно возвращают оптимизацию стоимости RVO или называют оптимизацию значения возврата, эта стоимость минимизируется.

1

Добавление к тому, что уже упоминалось ранее.

Когда оптимизация включена: NRVO или RVO гарантирует, что возвращаемое значение вычисляется на месте вместо того, чтобы копировать обратно вызывающему.

Когда все оптимизации отключены: Возврат вектора или строки как возврат объекта (в частности, объект типа контейнера, размер которого известен компилятору). Поскольку компилятор знает о размере возвращаемого объекта, у него достаточно информации для выделения требуемого пространства стека для копирования по значению.

Если вы пытаетесь вернуть массив (любого типа), как бы компилятор знал, сколько размера выделяется в стеке? Должен ли C++ принудительно возвращать массив фиксированного размера?

+0

Я узнал, что вектор v1 будет выделять v1 (информация заголовка) в стеке и хранить элементы данных v1 в куче. Здесь будет скопирован объект возврата (вектор b) на стек или кучу, прежде чем копировать его в c. Предыдущий ответ подразумевал, что вектор сохраняется в куче перед копированием. – Raghav

+0

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

+0

Взгляните на http://stackoverflow.com/questions/15701597/how-does-a-c-stdcontainer-vector-store-its-internals-element-address-acc – Arun

1

Возвращаемый объект запустит конструктор копирования, чтобы иметь векторный объект temp, который будет назначен b как конструктор копирования. Исходный объект будет уничтожен после выхода из области действия.

Большинство современных компиляторов имеют оптимизацию под названием «Оптимизация возвращаемого значения» (для краткости RVO). C++ 11 Ссылки RValue позволяют реализовать векторную реализацию, которая гарантирует ROV.

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

  • Нет связанных вопросов^_^