Почему вместо конструктора преобразования вызывается конструктор копирования?

Итак, в основном этот код:

class A {
};
class B { 
   B (const B& b) {}
public: 
   B (){}
   B (const A& a) {} 
};

int main()
{
   A a;
   B b1(a);  //OK
   B b2 = a; //Error
}

генерирует ошибку только для B b2 = a. И эта ошибка

error: 'B:: B (const B &) является закрытым

Почему он пытается вызвать конструктор копирования в дополнение к конструктору прямого преобразования?

Из сообщения об ошибке видно, что создан временный B, который затем используется для копирования-построения, но почему? Где это в стандарте?

Ответ 1

B b2 = a;

Это называется Инициализация копирования.

Он делает следующее:

  • Создайте объект типа B из a с помощью B (const A& a).
  • Скопируйте созданный временный объект в b2 с помощью B (const B& b).
  • Уничтожьте временный объект с помощью ~B().

Ошибка, которую вы получаете, не на шаге 1, а на шаге 2.

Где это в стандарте?

С++ 03 8.5 Инициализаторы
Параграф 14:

....
- Если тип назначения является (возможно, cv-квалифицированным) типом класса:
...
...
- В противном случае (т.е. Для остальных случаев инициализации копии) пользовательские последовательности преобразования, которые могут преобразовываться из типа источника в тип назначения или (когда используется функция преобразования) в его производный класс, перечисляются, как описано в 13.3.1.4, а лучший выбирается с помощью разрешения перегрузки (13.3). Если преобразование не может быть выполнено или неоднозначно, инициализация плохо сформирована. Выбранная функция вызывается с выражением инициализатора в качестве аргумента; если функция является конструктором, вызов инициализирует временный тип адресата. Результат вызова (который является временным для случая конструктора) затем используется для прямого инициализации, согласно вышеприведенным правилам, объекта, который является местом назначения инициализации копирования. В некоторых случаях реализации разрешено исключать копирование, присущее этой прямой инициализации, путем создания промежуточного результата непосредственно в инициализированном объекте; см. 12.2, 12.8.