Правила программирования на С и С++. Главы 7-8 - Перегруженной бинарной операции лучше всего быть встроенным (inline) псевдонимом операции приведения типа

ОГЛАВЛЕНИЕ

 

149. Перегруженной бинарной операции лучше всего быть встроенным (inline) псевдонимом операции приведения типа.

Это правило относится к числу тех, которые будут изменены с улучшением качества компиляторов. Рассмотрим следующее, простое для понимания дополнение к классу string из листинга 7 на странице 111.

class string

{

enum special_ { special };

string( special_ ) {}; // ничего не делает.

// ...

public:

const string operator+( const string ?r ) const;

// ...

};

//--------------------------------------------------------------

const string::operator+( const string ?r ) const

{

string tmp( special ); // создать пустой объект

tmp.buf = new char[ strlen(buf) + strlen(r.buf) + 1 ];

strcpy( tmp.buf, buf );

strcat( tmp.buf, r.buf );

return tmp;

}

Многие компиляторы, получив вышеуказанное, генерируют довольно неэффективный код. Объект tmp должен инициализироваться при вызове конструктора; здесь это не очень дорого, но обычно это ведет к значительно большим расходам. Конструктор копии должен быть вызван для выполнения оператора return, и сам объект также должен быть уничтожен.

Иногда вы можете улучшить такое поведение путем перегрузки встроенного псевдонима для операции приведения типа:

class string

{

string(const char *left, const char *right );public: const string string::operator+( const string ?r ) const ;};

//--------------------------------------------------------------

string::string(const char *left, const char *right )

{

buf = new char[ strlen(left) + strlen(right) + 1 ];

strcpy( buf, left );

strcat( buf, right );

}

//--------------------------------------------------------------

inline const string::operator+( const string ?r ) const

{

return string(buf, r.buf);}Более эффективные компиляторы здесь на самом деле рассматривают следующее: string s1, s2;

s1 + s2;

как если бы вы сказали следующее (вы не можете сделать этого сами, потому что buf является закрытым): string(s1.buf, s2.buf)

Полезный результат заключается в устранении неявного вызова конструктора копии в операторе return в первом варианте реализации.