C++ 初始化禁止复制的成员类

C++ 初始化禁止复制的成员类,c++,constructor,C++,Constructor,我有一个成员变量,它是一个禁止复制的类(复制赋值运算符被删除)。我想做一些检查来确定将成员初始化为什么,因此我需要在构造函数中而不是在和初始值设定项列表中执行此操作。似乎在进入MyClass的构造函数之前,成员变量m已经用默认构造函数初始化了,那么构造函数的意义是什么。。。对不起C++。 简单的例子: class MyClass { NonCopy m; MyClass() { // Complex checks if(success) {

我有一个成员变量,它是一个禁止复制的类(复制赋值运算符被删除)。我想做一些检查来确定将成员初始化为什么,因此我需要在构造函数中而不是在和初始值设定项列表中执行此操作。似乎在进入MyClass的构造函数之前,成员变量m已经用默认构造函数初始化了,那么构造函数的意义是什么。。。对不起C++。 简单的例子:

class MyClass {
    NonCopy m;
    MyClass() {
        // Complex checks
        if(success) {
            m("success");
        else {
            m("failure");
        }

    }
我看到的选择是:

  • 动态分配m
  • 放宽m的禁止复制要求

只要类具有有效的复制或移动构造函数,或者您使用的是C++17+,就可以创建一个执行逻辑的帮助函数,然后返回正确的对象。然后使用它初始化您的成员。那看起来像

class MyClass {
    NonCopy m;
    static NonCopy initialize_noncopy()
    {
        // Complex checks
        if(success) {
            return NonCopy("success");
        else {
            return NonCopy("faulure");
        }
    }
public:
    MyClass() : m(initialize_noncopy()) { }
};

只要类有一个有效的复制或移动构造函数,或者您使用的是C++17+,就可以生成一个执行逻辑的帮助函数,然后返回正确的对象。然后使用它初始化您的成员。那看起来像

class MyClass {
    NonCopy m;
    static NonCopy initialize_noncopy()
    {
        // Complex checks
        if(success) {
            return NonCopy("success");
        else {
            return NonCopy("faulure");
        }
    }
public:
    MyClass() : m(initialize_noncopy()) { }
};

嗯,您应该在构造函数体之前初始化成员变量

struct C {
    M member;
    C() : member("some arguments") { }
};
但这只有在您知道成员初始值设定项的参数时才有效!如果在构造函数主体中获得更多信息之前确实不想初始化
成员
,可以将其放入单个成员匿名
联合

struct C {
    union { M member; };
    C() { // member is not initialized
        // do whatever
        new(&member) M("some arguments"); // explicitly initialize
    }
    // now you have to write all the other special functions!
    ~C() { member.~M(); }
    C(C const &x) = delete;
    C(C &&x) { new(&member) M(std::move(x.member)); }
    C &operator=(C const &x) = delete;
    C &operator=(C &&x) { member = std::move(x.member); return *this; }
};

嗯,您应该在构造函数体之前初始化成员变量

struct C {
    M member;
    C() : member("some arguments") { }
};
但这只有在您知道成员初始值设定项的参数时才有效!如果在构造函数主体中获得更多信息之前确实不想初始化
成员
,可以将其放入单个成员匿名
联合

struct C {
    union { M member; };
    C() { // member is not initialized
        // do whatever
        new(&member) M("some arguments"); // explicitly initialize
    }
    // now you have to write all the other special functions!
    ~C() { member.~M(); }
    C(C const &x) = delete;
    C(C &&x) { new(&member) M(std::move(x.member)); }
    C &operator=(C const &x) = delete;
    C &operator=(C &&x) { member = std::move(x.member); return *this; }
};

今天我学到了一些新东西!我会把这个金块藏起来,说“我希望我永远不会有代码来做这件事。”但如果我有,现在我知道怎么做了。我今天学到了一些新东西!我会把这个金块藏起来,称为“我希望我永远不会有需要做这件事的代码。”但如果我有,现在我知道怎么做了。将决策部分移到另一个函数,而不是初始化,不是更好吗。因此,类似于
MyClass():m(decise()?“success”:“failure”){}
@ayxanhanhaqverdili取决于具体情况。如果您不能使用C++17,或者该类没有复制/移动C'tor,那么是的,这可能是最好的方法。但我试图避免它,并尝试将该逻辑放入命名函数中。此外,虽然示例代码中的检查很简单,但注释中表示复杂的检查,这很可能意味着在OP的实际代码中,像这样的简单检查可能不够。因此,我展示了这种方法。将决策部分移到另一个函数,而不是初始化,不是更好吗。因此,类似于
MyClass():m(decise()?“success”:“failure”){}
@ayxanhanhaqverdili取决于具体情况。如果您不能使用C++17,或者该类没有复制/移动C'tor,那么是的,这可能是最好的方法。但我试图避免它,并尝试将该逻辑放入命名函数中。此外,虽然示例代码中的检查很简单,但注释中表示复杂的检查,这很可能意味着在OP的实际代码中,像这样的简单检查可能不够。因此,我展示了这种方法。