Программирование >>  Инициализация объектов класса, структура 

1 ... 231 232 233 [ 234 ] 235 236 237 ... 395


переписанная компилятором функция

в случае принятия предлагавшегося расширения яза

void

operator+( Matrix sresult, const Matrixs m1, const Matrixs m2 ) name result {

вгчисть результат

параметр-ссылку:

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

Matrix c = a + b;

Matrix c;

было бы трансформировано в

operator+(c, a, b);

Это расширение так и не стало частью языка, но предложенная оптимизация прижилась. Компилятор в состоянии распознать, что возвращается объект класса и выполнить трансформацию его значения и без явного расширения языка. Если дана функция общего

classType

functionName( paramList ) {

classType namedResult; волнить какие-то д

PmP onoml.

действия

return namedResult; вида:

то компилятор самостоятельно трансформирует как саму функцию, так и все обращения к ней:

Matrixs

operator+( const Matrixs m1, const Matrixs m2 ) name result {

Matrix result; ...

return result;

Тогда компилятор мог бы самостоятельно переписать функцию, добавив к ней третий



void

functionName( classType snamedResult, paramList ) {

вычислить результат и разместить его по адресу namedResult

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

И последнее замечание об эффективности работа: с объектами в С++. Инициализация объекта класса вида

Matrix c = a + b;

всегда эффективнее присваивания. Например, результат следующих двух инструкций

Matrix c;

такой же, как и в предыдущем случае:

c = a + b;

for ( int ix = 0; ix < size-2; ++ix ) {

Matrix matSum = mat[ix] + mat[ix+1];

...

но объем требуемых вычислений значительно больше. Аналогично эффективнее писать:

Matrix matSum; for ( int ix = 0; ix < size-2; ++ix ) { matSum = mat[ix] + mat[ix+1];

...

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

Point3d p3 = operator+( p1, p2 );

можно безопасно трансформировать:



Псевдокод на C++ Point3d p3;

operator+( p3, p1, p2 );

Point3d p3;

преобразование

p3 = operator+( p1, p2 );

Псевдокод на C++

небезопасно в случае присваивания

operator+( p3, p1, p2 );

небезопасно.

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

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

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

Point3d p3; объекту. Например, следующий фрагмент

p3 = operator+( p1, p2 );

Псевдокод на C++ Point3d temp;

operator+( temp, p1, p2 ); p3.Point3d::operator=( temp );

трансформируется в такой:

temp.Point3d::~Point3d();



1 ... 231 232 233 [ 234 ] 235 236 237 ... 395

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика