Добрый день.
Никто не подскажет почему такой код компилируется только когда у Foo определен конструктор копирования, при этом он не вызывается.
Когда конструктор копирования отсутствует, "ругается на" (что он delete) конструктор копирования fstream.
class Foo
{
public:
Foo(){}
Foo(const Foo& f){}
private:
std::fstream f;
};
class Bar
{
public:
Bar(int i){}
Foo foo;
};
std::vector<Bar> v;
v.emplace_back(5);
Здравствуйте, HolyNick, Вы писали:
HN>Хотя нет — не снимается.
Потому что вопреки досужим мнениям, язык с++ является статически строго типизированным. А это означает, что он на нем нельзя выполнять семантику присвоения теплого с мягким:
some val = 10;
Что здесь происходит?
Некоторые думают, что данный код эквивалентен:
some val(10);
Но это ошибочное мнение. Поскольку язык строго типизированный, то когда используется семантика присвоение (символ '='), в левой и в правой части должны находится идентичные типы данных.
Поэтому настоящий эквивалент кода выглядит так:
some val = some(10);
Компилятор пытается создать в правой части временный объект такого же типа, и только потом использовать семантику присвоения.
Окончательная версия эквивалента получается такой:
some val( some(10) );
При этом срабатывает стандартная NRVO-оптимизация, и мы не наблюдаем вызова конструктора копии. Даже в дебаге не наблюдаем.
Вообще согласно стандарту, вы не должны закладываться на наблюдаемость копирующих конструкторов, потому что они являются претендентами на оптимизацию.
Здравствуйте, HolyNick, Вы писали:
HN>Добрый день. HN>Никто не подскажет почему такой код компилируется только когда у Foo определен конструктор копирования, при этом он не вызывается.
предположу, что для типа Bar нужно предоставить либо конструктор копирования, либо конструктор перемещения. для emplace_back тип должен быть EmplaceConstructible, MoveInsertable, MoveAssignable, Erasable
std::fstream не имеет конструктора копии или конструктора перемещения, поэтому компилятор не смог сгенерировать соответствующие конструкторы для типа Foo. когда вы вручную определяете Foo(const Foo&) {}, то компилятору становится хорошо, но пустой конструктор копирования не копирует std::fstream, ваше приложение может неправильно работать из-за этого
все это можно найти в стандарте глава 23 Containers library [containers]