В духе «выбрать контейнеры с умом», я заинтересован в том, что это лучший способ, чтобы сохранить либо ровно одинилине объекта, например, в качестве члена в классе. Это может иметь место, например, если удерживаемый объект дорог для вычисления и должен каким-то образом кэшироваться (или любого другого типа «позднего» создания).Каков предпочтительный способ хранения одного или любого объекта в C++?
Очевидными кандидатами являются std::vector
и std::unique_ptr
, например:
class object_t;
class foo_t {
std::unique_ptr<object_t> m_cache;
public:
object_t getObject() {
if(not m_cache) {
m_cache.reset(new object_t()); // object creation is expensive
}
return object_t(*m_cache);
}
};
и точно так же с вектором (или почти любой другой контейнер):
class object_t;
class foo_t {
std::vector<object_t> m_cache;
public:
object_t getObject() {
if(m_cache.empty()) {
m_cache.push_back(object_t()); // object creation is expensive
}
return m_cache.front();
}
};
Конечно, есть еще возможность имеют некоторую логическую переменную, которая сохраняет состояние объекта:
class object_t;
class foo_t {
bool cache_healthy;
object_t m_cache;
public:
foo_t() : cache_healthy(false), m_cache() {}
object_t getObject() {
if(not cache_healthy) {
m_cache = object_t();
cache_healthy = true;
}
return m_cache;
}
/* do other things that might set cache_healthy to false. */
};
Из трех примеров, мне нравится последний, тем меньше, потому что он либо создает объект дважды, либо, если я изменяю object_t
на «дешевый»/неполный конструктор, может вернуть недопустимый объект.
Решение с вектором, которое мне больше не нравится семантически, потому что вектор (или любой другой тип контейнера) может создать впечатление, что может быть больше одного объекта.
Теперь, думая об этом снова, я думаю, что мне больше всего нравится решение указателя, но я не совсем этому доволен и хотел бы услышать, если вы знаете какое-либо решение, которое является самым элегантным в этом случае.
'станда: : 'или' boost.optional'. –
спасибо, я не знал об этой функции. Однако это C++ 17, но будет помнить об этом. – jafasi
для меня решение с 'std :: unique_ptr' кажется лучшим,' vector' кажется довольно странным для этой цели - мне было бы страшно, что в какой-то реализации будет использоваться начальный размер не 0. Идея с object_t будет создавать объект дважды - так что это не хорошо - что, если ваш кеш имеет несколько больших полей. необязательное решение - вероятно, будет сильно рекламироваться, но первоначально использует размер вашего объекта кэша - возможно, это не такое идеальное решение - если у вас много кешей, и не все из них используются (и объект очень большой). – marcinj