Здравствуйте, <Аноним>, Вы писали:
А>Какой из вариантов прeдпочтительнее?
В данном случае все пофигу. А вот если x -- user-defined тип, то второй пример проигрывает из-за лишнего вызова конструктора по умолчанию.
... << RSDN@Home 1.2.0 alpha rev. 655>>
"Бог не терпит голой сингулярности" -- Роджер Пенроуз
хм, я то думал первый вариант быстрее — а оказалось одинаково...
Может кто меня поправит?
Re[2]: какой код эффективнее?
От:
Аноним
Дата:
08.09.06 05:51
Оценка:
Здравствуйте, CiViLiS, Вы писали:
CVL>Здравствуйте, <Аноним>, Вы писали:
А>>Какой из вариантов прeдпочтительнее? CVL>В данном случае все пофигу. А вот если x -- user-defined тип, то второй пример проигрывает из-за лишнего вызова конструктора по умолчанию.
Не могу понять почему в случае классов лишний вызов конструктора?
Здравствуйте, <Аноним>, Вы писали:
А>Не могу понять почему в случае классов лишний вызов конструктора?
Могу предложить поэксперементировать вот с этим примером:
struct A
{
A()
{
i = -15;
std::cout << __FUNCTION__ << std::endl;
}
int i;
}
struct B
{
A a;
B()
{ // <- вот здесь инициализируются все поля класса B. То есть вызывается A::A().
std::cout << i << std::endl;
a.i = 10; // а здесь уже не инициализация, а изменение.
std::cout << i << std::endl;
}
}
B b;
Программа выведет
A::A
-15
10
А если немного изменить класс A -- убрать дефолтный конструктор, то есть конструктор без параметров:
struct A
{
A(int q)
{
i = q;
std::cout << __FUNCTION__ << std::endl;
}
int i;
}
то компилятор на ругнется в конструкторе B():
error C2512: 'A' : no appropriate default constructor available
За подробностями лучше почитать Липпмана или Страуструпа. К сожалению сейчас ни того ни другого под рукой нету, поэтому цитаты не приведу. Зато естб стандарт, но там искать влом
... << RSDN@Home 1.2.0 alpha rev. 655>>
"Бог не терпит голой сингулярности" -- Роджер Пенроуз
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, CiViLiS, Вы писали:
CVL>>Здравствуйте, <Аноним>, Вы писали:
А>>>Какой из вариантов прeдпочтительнее? CVL>>В данном случае все пофигу. А вот если x -- user-defined тип, то второй пример проигрывает из-за лишнего вызова конструктора по умолчанию.
А>Не могу понять почему в случае классов лишний вызов конструктора?
При конструировании объекта класса сначала конструируются его базовые подобъекты, затем члены, затем исполняется тело конструктора. В варианте 1 в списке инициализации член x инициализируется с помощью конструктора с параметром, а тело конструктора metal_safe_for_x_variable пусто. В варианте 2 член x инициализируется с помощью конструктора по умолчанию, затем выполняется тело metal_safe_for_x_variable, в котором есть еще одно присваивание.
В общем случае вариант 1 эффективнее.
Здравствуйте, Аноним, Вы писали:
CVL>>В данном случае все пофигу. А вот если x -- user-defined тип, то второй пример проигрывает из-за лишнего вызова конструктора по умолчанию.
А>Не могу понять почему в случае классов лишний вызов конструктора?
Вариант 2.
class metal_safe_for_x_variable{
private:
int x;
public:
metal_safe_for_x_variable(int x_){x=x_;}
}
Перед вызовом конструктора класса, т.е. перед его открывающей скобкой '{', происходит создание всех внутренних элементов класса, и твоего 'x'- тоже (для него вызывается конструктор по-умолчанию). Затем при входе в конструктор создается локальная копия 'x_'(вызов констуктора копирования). И наконец x=x_; копирует содержимое x_ в твой x.
В Варианте 2. перед открывающей скобкой конструктора ты сам вызываешь сразу конструктор копирования для 'x', т.е. в принципе экономишь ты только на пропуске операции x=x_;,
т.к. при входе в конструктор опять таки создается локальная копия x_.
Лучший вариант — передать параметр 'x_' по ссылке, и перед скобкой сделать вызов конструктора копирования. В этом случае ты получаешь всего один вызов конструктора копирования, который выполняет как раз то, что тебе нужно — инициализирует 'x' содержимым 'x_'; и ни каких тебе созданий локальных переменных
class metal_safe_for_x_variable{
private:
x_class x;
public:
metal_safe_for_x_variable(x_class& x_):x(x_){}
}