Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;联合用法_C++_Unions - Fatal编程技术网

C++ C++;联合用法

C++ C++;联合用法,c++,unions,C++,Unions,到目前为止,我只是使用联合存储成员A或成员B。 现在,我确实发现自己需要在运行时更改使用过的成员 union NextGen { std::shared_ptr<TreeRecord> Child = nullptr; std::vector<std::shared_ptr<TreeRecord>> Children; }; union-NextGen{ std::shared_ptr Child=nullptr; 性病媒儿童; }; 我目

到目前为止,我只是使用联合存储成员A或成员B。
现在,我确实发现自己需要在运行时更改使用过的成员

union NextGen {
    std::shared_ptr<TreeRecord> Child = nullptr;
    std::vector<std::shared_ptr<TreeRecord>> Children;
};
union-NextGen{
std::shared_ptr Child=nullptr;
性病媒儿童;
};
我目前的用法:

void TreeRecord::AddChild(const std::shared_ptr<TreeRecord>& NewChild) {
    if(_childCount == 0) {
        _nextGeneration.Child = NewChild;
        _childCount++;
    } else if(_childCount == 1) {
        //This is not clear to me:
        //Do I have to set Child to nullptr first?
        //Do I need to clear the Children vecor?
        //Or will it work like this?
        _nextGeneration.Children.push_back(_nextGeneration.Child);
        _nextGeneration.Children.push_back(NewChild);
        _childCount++;
    } else {
        _nextGeneration.Children.push_back(NewChild);
        _childCount++;
    }
}
void TreeRecord::AddChild(const std::shared\u ptr&NewChild){
如果(_childCount==0){
_nextGeneration.Child=NewChild;
_childCount++;
}else如果(_childCount==1){
//我不清楚这一点:
//我必须先将Child设置为nullptr吗?
//我需要清理孩子们吗?
//还是会像这样工作?
_nextGeneration.Children.push_back(_nextGeneration.Child);
_下一代。儿童。推回(新儿童);
_childCount++;
}否则{
_下一代。儿童。推回(新儿童);
_childCount++;
}
}

新实施(尝试):

typedef std::shared_ptr<TreeRecord> singlechild_type;
typedef std::vector<std::shared_ptr<TreeRecord>> children_type;



union {
    singlechild_type _child;
    children_type _children;
};



void TreeRecord::AddChild(const singlechild_type& NewChild) {
    if(_childCount == 0) {
        _child = NewChild;
        _childCount = 1;

    } else if(_childCount == 1) {
        singlechild_type currentChild = _child; //Copy pointer
        _child.~singlechild_type(); //Destruct old union member
        new (&_children) children_type(); //Construct new union member
        _children.push_back(currentChild); //Add old child to vector
        _children.push_back(NewChild); //Add new child to vector
        _childCount = 2;

    } else {
        _children.push_back(NewChild);
        _childCount++;
    }
}
typedef std::shared_ptr singlechild_type;
typedef std::向量子类型;
联合{
独生子女(类型)子女;;
儿童型儿童;
};
void TreeRecord::AddChild(const singlechild_type和NewChild){
如果(_childCount==0){
_孩子=新孩子;
_childCount=1;
}else如果(_childCount==1){
singlechild\u type currentChild=\u child;//复制指针
_child.~singlechild_type();//销毁旧的联合成员
新建(&_children)children_type();//构造新的联合成员
_children.push_back(currentChild);//将旧的子对象添加到向量
_children.push_back(NewChild);//将新的子对象添加到向量
_儿童数=2;
}否则{
_儿童。推回(新儿童);
_childCount++;
}
}
您需要一个兼容的编译器。了解-s

通常,需要显式调用旧联合成员的析构函数,然后调用新联合成员的构造函数。实际上,由于实际的
union
是匿名的,并且是某个类的成员,您最好:

class TreeRecord;

class TreeRecord {
   bool hassinglechild;
   typedef std::shared_ptr<TreeRecord> singlechild_type;
   typedef std::vector<std::shared_ptr<TreeRecord>> children_type;
   union {
     singlechild_type child;  // when hassinglechild is true
     children_type children;  // when hassinglechild is false
   }
   TreeRecord() : hassinglechild(true), child(nullptr) {};
   void set_child(TreeRecord&ch) {
     if (!hassinglechild) {
       children.~children_type();
       hassinglechild = true;
       new (&child) singlechild_type(nullptr);
     };
     child = ch;
   }
   /// other constructors and destructors skipped
   /// more code needed, per rule of five
}
类树记录;
类树记录{
布尔·哈辛格勒;
typedef std::shared_ptr singlechild_type;
typedef std::向量子类型;
联合{
singlechild_type child;//当hassinglechild为true时
children\u type children;//当hassinglechild为false时
}
TreeRecord():hassinglechild(true),child(nullptr){};
无效集合(树记录和ch){
如果(!hassinglechild){
children.~children_type();
hassinglechild=真;
新的(&child)单子女_类型(nullptr);
};
child=ch;
}
///跳过了其他构造函数和析构函数
///根据第五条规则,需要更多代码
}
请注意,我显式调用析构函数
~children\u type()
,然后使用placement
new
显式调用
child
的构造函数

别忘了遵循规则。所以你需要更多的代码

另见

顺便说一句,您的代码建议您区分有
子对象的情况和有
子对象的单元素向量的情况。这是自愿和有意义的吗


在一些语言中,尤其是Ocaml中,标记的联合(也称为和类型)比在C++11中更容易定义和实现。。。。请参见wikipage of.

注意,使用
联合的多个元素同时调用未定义的行为,例如

    _nextGeneration.Children.push_back(_nextGeneration.Child);

正如@BasileStarynkevitch提到的,一种方法是避免这是一个带标签的联盟。

甚至没有想过!你说的“一般”是什么意思?这是正确的答案,但如果你详细解释一下就好了。我不会有一个元素向量。对于0或1个元素,我使用Child,对于多于1个元素,我切换到vector。还是我犯了个错误。。。?(我还在读你的代码)我正在使用一个带标签的并集,只是没有使用布尔标识符,而是使用了“size\t\u childCount”,当使用Child时,它是0或1。但是
std::vector
带有它自己的
\u childCount
作为它的
size()
,所以你只需要一个布尔值flag@LightnessRacesinOrblit:我刚才提到了,但是boost的错误在于它需要额外的依赖性。有时人们不喜欢这样(我理解这种观点)。