Предположим, у вас есть класс под названием Product, определенный следующим образом:
class Product
{
public:
Product(const char *name, int i);
Product(Product &&rhs);
Product(const Product &rhs);
~Product();
private:
const char *m_name;
int m_i;
};
и вы инициализируете такую переменную:
auto p = Product{"abc",123};
Я думал, что стандарт диктует, что компилятор должен логически делать следующее:
- создать временный продукт
- move-construct p (с использованием временного продукта)
Но компилятору было разрешено оптимизировать это так, чтобы p строился напрямую.
Я проверил это (Visual Studio 2013), и действительно, компилятор оптимизирует это, даже если у нас есть собственный (не по умолчанию) конструктор перемещения. Это хорошо.
Однако, если я явно удалю конструктор копирования и перемещения, например:
class Product
{
public:
Product(const char *name, int i);
Product(Product &&rhs) = delete;
Product(const Product &rhs) = delete;
~Product();
private:
const char *m_name;
int m_i;
};
Инициализация auto + brace все еще компилируется. Я думал, что компилятор должен был предотвратить это, потому что не разрешено копирование или перемещение.
Как ни странно, если я сделаю удаленный конструктор копирования и перемещения закрытым, например:
class Product
{
public:
Product(const char *name, int i);
~Product();
private:
Product(Product &&rhs) = delete;
Product(const Product &rhs) = delete;
const char *m_name;
int m_i;
};
Тогда инициализация auto + brace больше не компилируется.
error C2248: 'Product::Product' : cannot access private member declared in class 'Product'
Это ожидаемое поведение? Это ошибка в Visual Studio 2013 (обновление 3)?
Примечание: я попытался скомпилировать это на ideone, и там он действительно отказывается компилировать инициализацию, когда конструкторы копирования и перемещения удаляются (и становятся общедоступными). Так что я думаю, что это ошибка Visual Studio.