2013-06-09 3 views
3

В приведенном ниже коде, почему первый решительность вызова на catchClass(aClass&) и учитывая временный характер в качестве параметра во втором Invoke catchClass(const aClassCatcher&)C++: специальное поведение для временных

#include <iostream> 

using namespace std; 

class aClassCatcher{}; 

class aClass{ 
public: 
    operator aClassCatcher(){ 
     return aClassCatcher(); 
    } 
}; 

void catchClass(aClass&){ 
    cout << __FUNCSIG__ << endl; 
} 
void catchClass(const aClassCatcher&){ 
    cout << __FUNCSIG__ << endl; 
} 

int main() 
{ 
    aClass aC; 
    catchClass(aC); // calls catchClass(aClass&) 

    catchClass(aClass()); // calls catchClass(const aClassCatcher&) 

} 

В случае, если вы задаетесь вопросом, где я наткнулся это, я пытаюсь понять конструкторы перемещения, как описано в статье, в статье Dobb's.

+1

Поскольку временные лица не могут связываться с неконстантными ссылками lvalue. – juanchopanza

ответ

5

Прежде всего, важно заметить, что поведение, которое вы наблюдаете, не связано с семантикой перемещения или отсутствием или отсутствием переместить конструктор. Вы можете запустить свой пример в компиляторе C++ 03 и наблюдать точное тождественное поведение.

Объяснение поведения вы наблюдаете, что Lvalue ссылки непредставленных const (aClass&) может связываться только с lvalues, в то время как Lvalue ссылки на const (const aClassCatcher&) могут связываться как с lvalues ​​и rvalues ​​(но не позволяют изменяя объект, к которому они привязаны, поскольку они являются ссылками на const).

Если вы работаете с компилятором Microsoft VC, это может показаться вам странным. Причина в том, что MSVC имеет нестандартное расширение, которое позволяет привязывать значения r к значениям lvalue для не const. Это IMO плохой, и это не так, как работает Standard C++.

Теперь, когда вы указали временное, что является rvalue, компилятор не имеет шансов, но выбирает перегрузку, которая принимает ссылку lvalue на const. Перегрузка, берущая отношение lvalue к не const, просто не жизнеспособна из-за того, что я ранее писал.

Теперь в вашем случае вторая перегрузка жизнеспособна, поскольку существует определенное пользователем преобразование от aClass до aClassCatcher. Это преобразование возвращает временный тип aClassCatcher, а ссылки lvalue на const могут привязываться к временным. Поэтому выбирается вторая перегрузка.

С другой стороны, если вы обеспечиваете lvalue, обе перегрузки являются жизнеспособными, но тот, кто принимает ссылку на lvalue для не const, является предпочтительным, поскольку преобразование не требуется.

+0

эй ... я просто переименовал aClass__ в aClassCatcher, чтобы избежать путаницы ... немного нового здесь ... плохо отредактируйте свой ответ для потомков ... :-) спасибо ... – user1055604

+0

Я понимаю, что вы подразумеваете под плохим microsoft extension ... cos, когда я комментирую 'catchClass (const aClassCatcher &)', я получаю оба вызова, разрешающие 'catchClass (aClass &)' – user1055604

+0

@ user1055604: Действительно, и это плохо;) Я отредактирую ответ, чтобы соответствовать редактированию ваш вопрос –

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