Как я могу сделать класс со ссылочным членом данных конструктивным без аргументов?
У меня есть класс, скажем C, где один из данных члена, скажем, X, зависит от ввода пользователя. Пользовательский ввод может отличаться при каждом запуске, и в моем текущем дизайне все экземпляры моих классов хранят ссылку на один и тот же объект X.
Как я могу настроить дизайн так, чтобы он позволял конструктору по умолчанию без аргументов?
Таким образом, я могу использовать конструктор копирования / назначения, создавать массивы C, использовать временное значение и т. Д.
Ниже приведен минимальный рабочий пример, иллюстрирующий мой вопрос. В случае, с которым я работаю, тег относится к некоторым внешним ресурсам.
#include <iostream>
#include <string>
#include <vector>
#include <cassert>
using namespace std;
struct Tag {
int N;
string tag;
};
template<typename T>
struct Vec {
const Tag& tag;
T* vec;
Vec(const Tag& tag_) : tag(tag_) {
vec = new T[tag.N];
}
~Vec() {
delete [] vec;
}
};
Tag make_tag(vector<string>& args) {
assert(args.size() == 3);
int N = stoi(args[1]);
return Tag {N, args[2]};
}
vector<string> arguments(int argc, char* argv[]) {
vector<string> res;
for(int i = 0; i < argc; i++)
res.push_back(argv[i]);
return res;
}
int main(int argc, char* argv[]) {
vector<string> args = arguments(argc, argv);
Tag tag0 = make_tag(args);
Tag tag1;
Vec<double> vec(tag0);
return 0;
}
1 ответ
Как я могу настроить дизайн так, чтобы он позволял конструктору по умолчанию без аргументов?
Ну, три варианта, которые я бы предложил:
Необычный способ: использовать
std::optional<std::reference_wrapper<T>>
член.std::reference_wrapper
для размещения ссылки там, где вы не уверены, что ссылка будет работать как есть.std::optional<T>
держит либоT
илиnullopt
(т.е. без стоимости). Это имеет преимущество инициализатора по умолчанию дляoptional
без аргументов, так что вы можете использовать конструктор по умолчанию для без аргументов в случае C.Старая школа: используйте простой указатель вместо ссылки. Инициализируйте это
nullptr
на строительство без аргументов. (@RemyLebeau также предложил это в комментарии.)Умный путь RAII: замени свой класс
C
сstd::optional<C>
, Это означает, что конструкция без аргументов фактически не создает C - она просто сохраняетnullopt
откладывая фактическое строительство на потом. Это решение актуально, когда вы должны поддерживать инвариантC
хранение ресурсов на протяжении всего своего существования; оно также имеет преимущество в том, что справочный членC
какconst
,
Я намеренно не рассматриваю ваш MWE (вы сказали, что это просто иллюстративно), и предлагаю более общий ответ.