如何使具有引用数据成员的Class可以无参数构造?

时间:2018-10-26 21:11:57

标签: c++ constructor reference class-design const-reference

我有一个类,例如C,其中一个成员数据(例如X)取决于用户输入。每次运行时,用户输入可能会有所不同,在我当前的设计中,我的类的所有实例都存储对同一对象X的引用。

我如何调整设计,使其允许不带参数的默认构造函数?

这样,我可以使用副本分配/副本构造函数,创建C数组,使用临时右值等。

以下是说明我的问题的最小工作示例。在我使用的情况下,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;
}

1 个答案:

答案 0 :(得分:1)

  

我如何调整设计,使其允许不带参数的默认构造函数?

好吧,我建议三个选择:

  • 奇特的方式:使用一个std::optional<std::reference_wrapper<T>>成员。 std::reference_wrapper用于在您不确定引用是否可以按原样工作的情况下放置参考。 std::optional<T>持有Tnullopt(即无值)。这样做的好处是optional的默认初始化程序是无参数的,因此对于C的无参数情况,您可以使用默认构造函数。

  • 老式的方法:使用普通指针成员而不是引用。在无参数构造时将其初始化为nullptr。 (@RemyLebeau也在评论中建议了这一点。)

  • 聪明的RAII方式:用C替换您的课程std::optional<C>。这意味着无参数的构造实际上并没有构造C-它仅保留nullopt,从而延迟了稍后的实际构造。当您必须在整个C中保持资源的不变性时,此解决方案才有意义。这样做还有一个好处,就是将C的引用成员保留为const

我故意不考虑您的MWE(您说这只是示例性的),而是提供了更笼统的答案。