Небольшой C++ tip:
Создавать объекты std::optional лучше всего через std::make_optional или вызов emplace(), тогда при создании объекта будет один вызов конструктора.
Написал небольшой пример:
#include <iostream>
#include <optional>
class Element
{
public:
Element()
{
std::cout << "Default CNTR" << std::endl;
}
Element(const Element&)
{
std::cout << "Copy CNTR" << std::endl;
}
Element(Element&&)
{
std::cout << "Move CNTR" << std::endl;
}
~Element()
{
std::cout << "DSTR" << std::endl;
}
void TraceData() const
{
std::cout << "[" << posX << ":" << posY << "] " << (visible ? "visible" : "hidden") << "\n";
}
private:
int posX{0};
int posY{0};
bool visible{false};
};
int main()
{
// One constructor call and one destructor call
{
auto element = std::make_optional<Element>();
element->TraceData();
}
std::cout << "-------------\n";
// One constructor call and one destructor call
{
std::optional<Element> element;
auto& elem = element.emplace();
elem.TraceData();
}
std::cout << "-------------\n";
// Two constructor calls and two destructor calls
{
auto element = std::optional<Element>(Element{});
element->TraceData();
}
return 0;
}
Вывод будет следующий:
Default CNTR
[0:0] hidden
DSTR
-------------
Default CNTR
[0:0] hidden
DSTR
-------------
Default CNTR
Move CNTR
DSTR
[0:0] hidden
DSTR
Видно что в третьем случае создался объект через default'ный конструктор, а потом вызвался конструктор переноса и далее лишний деструктор.