[英]How can I make a Class with reference data member constructible with no arguments?
I have a class, say C, where one of the member data, say X, depends on user input.我有一个类,比如 C,其中一个成员数据,比如 X,取决于用户输入。 The user input may differ on every run, and in my current design, all instances of my classes stores a reference to the same object X.每次运行时用户输入可能不同,在我当前的设计中,我的类的所有实例都存储对同一对象 X 的引用。
How can I tweak the design so that it allows default constructor with no arguments?如何调整设计以允许没有参数的默认构造函数?
This way I can use copy assignment/copy constructor, make arrays of C, use temporary rvalue etc.这样我就可以使用复制赋值/复制构造函数,制作 C 数组,使用临时右值等。
Below is a minimal working example illustrating my question.以下是说明我的问题的最小工作示例。 In the case I work with, Tag refers to some external resources.在我使用的情况下,Tag 指的是一些外部资源。
#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;
}
How can I tweak the design so that it allows default constructor with no arguments?如何调整设计以允许没有参数的默认构造函数?
Well, three options that I would suggest:好吧,我建议的三个选项:
The fancy way : Use a std::optional<std::reference_wrapper<T>>
member.奇特的方法:使用std::optional<std::reference_wrapper<T>>
成员。 std::reference_wrapper
is for putting reference in place where you're not sure a reference would just work as-is. std::reference_wrapper
用于在您不确定引用是否按原样工作的地方放置引用。 std::optional<T>
holds either a T
or a nullopt
(ie no-value). std::optional<T>
持有T
或nullopt
(即无值)。 This has the benefit of the default initializer for the optional
being argument-less, so you can possibly use a default constructor for the argument-less case of C.这有一个好处是optional
的默认初始化器是无参数的,所以你可以为 C 的无参数情况使用默认构造函数。
The old-school way : Use a plain pointer member instead of the reference.老派方式:使用普通指针成员而不是引用。 Initialize it to nullptr
on no-argument construction.在无参数构造上将其初始化为nullptr
。 (@RemyLebeau also suggested this in a comment.) (@RemyLebeau 也在评论中提出了这一点。)
The smart-ass RAII way : Replace your class C
with an std::optional<C>
.聪明的 RAII 方式:用std::optional<C>
替换你的类C
。 This means that argument-less construction doesn't actually construct a C - it just keeps a nullopt
, delaying the actual construction for later.这意味着无参数构造实际上并不构造 C - 它只是保留一个nullopt
,将实际构造推迟到以后。 This solution is relevant when you must maintain the invariant of C
holding resources throughout its existence;当您必须在整个存在期间保持C
持有资源的不变性时,此解决方案是相关的; it also has the benefit of keeping the reference member of C
as const
.它还具有将C
的引用成员保持为const
的好处。
I purposely am not considering your MWE (you said it is just illustrative), and am offering a more general answer.我故意不考虑您的 MWE(您说这只是说明性的),而是提供更一般的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.