У меня есть класс с очень большой полезной нагрузкой, поэтому очень дорого создавать/копировать/перемещать экземпляр этого класса. Поскольку они не изменятся после завершения инициализации приложения, нет необходимости создавать временные объекты этого класса. Мне нужно только кэшировать объекты в контейнере (std::map
) и при необходимости предлагать «константную ссылку».
Следует подчеркнуть, что я ищу решение, которое может избежать двойного создания или ненужного копирования объекта перед его добавлением в контейнер (я не думаю, что решение, подобное предложенному @getsoubl, может решить проблему, потому что это не исключает дублирования или ненужного копирования).
Поэтому я хочу расположить метод конструктора в разделе «частный/защищенный» тела класса, чтобы запретить любое создание/копирование/перемещение за пределы «фабричного метода». Ниже приведено мое оригинальное решение:
class MyClass {
public:
// methods of the class
static const MyClass & findObject( int iKey ) {
auto pair = mapObjects.try_emplace( iKey, iKey );
if ( pair.second )
cout << "New object has been created" << endl;
return pair.first->second;
};
// deleted
MyClass() = delete;
MyClass( MyClass & ) = delete;
MyClass( MyClass && ) = delete;
MyClass( const MyClass & ) = delete;
MyClass( const MyClass && ) = delete;
MyClass & operator=( MyClass & ) = delete;
MyClass & operator=( MyClass && ) = delete;
MyClass & operator=( const MyClass & ) = delete;
MyClass & operator=( const MyClass && ) = delete;
private:
// vars of the class
static map<int, MyClass> mapObjects;
// vars of instance
string some_heavy_payload;
// methods of instance
MyClass( int iKey ) :
some_heavy_payload( std::to_string( iKey ) ) {};
};
map<int, MyClass> MyClass::mapObjects;
int main() {
const MyClass & obj = MyClass::findObject( 1 );
return EXIT_SUCCESS;
};
Но я столкнулся с противоречием, что «std::try-emplace» НЕ может также вызывать конструктор MyClass. Компилятор сообщает: «ошибка: ‘MyClass::MyClass(int)’ является закрытым в этом контексте».
Итак, я попробовал решение 2:
class MyClass {
public:
// methods of the class
static const MyClass & findObject( int iKey ) {
if ( mapObjects.find( iKey ) == mapObjects.cend() )
mapObjects[iKey] = MyClass( iKey );
return mapObjects[iKey];
};
// deleted
MyClass() = delete;
MyClass( MyClass & ) = delete;
MyClass( MyClass && ) = delete;
MyClass( const MyClass & ) = delete;
MyClass( const MyClass && ) = delete;
MyClass & operator=( MyClass & ) = delete;
MyClass & operator=( const MyClass & ) = delete;
MyClass & operator=( const MyClass && ) = delete;
private:
// vars of the class
static map<int, MyClass> mapObjects;
// vars of instance
string some_heavy_payload;
// methods of instance
MyClass( int iKey ) {
some_heavy_payload = std::to_string( iKey );
};
MyClass & operator=( MyClass && src ) {
some_heavy_payload = std::move( src.some_heavy_payload );
return *this;
};
};
map<int, MyClass> MyClass::mapObjects;
int main() {
const MyClass & obj = MyClass::findObject( 1 );
return EXIT_SUCCESS;
};
На этот раз я получил ошибку: «использование удаленной функции ‘MyClass::MyClass()’». Я предполагаю, что это результат оператора "[]" std::map, потому что он пытается вызвать конструктор MyClass по умолчанию.
Как я могу это сделать?