在向量C ++ 14中的结构内部的并集中创建和存储字符串(无限制并集)

时间:2018-09-13 15:00:10

标签: c++ c++11 vector

谁能解释一下如何将一个字符串(在结构内部的并集中)分配并推入向量中?这可能吗?引导程序是否试图访问无效的内存?

#include <iostream>
#include <string>
#include <vector>

using namespace std;

typedef struct {
            int height;
            int width;
        } Page;

typedef struct varstruct{
            int test;
            union uni{
                Page page;
                int intVar;
                string stringVar;
                uni(){
                 new (&stringVar) std::string();
                }
                ~uni(){}
            } VarUnion;
            varstruct(){}
            ~varstruct(){}
        } VariableDataStruct;

vector<VariableDataStruct> List;

int main()
{
    VariableDataStruct structeg;
    structeg.test = 1;
    structeg.VarUnion.stringVar = "Test";
    List.push_back(structeg);
    cout<<structeg.VarUnion.stringVar<<endl;
    structeg.VarUnion.stringVar.~basic_string();
    return 0;
}

在没有“ List.push_back(structeg);”的情况下,代码可以正常工作声明。除此语句外,还会出现以下错误

In file included from /usr/include/c++/4.8.3/x86_64-redhat-linux/bits/c++allocator.h:33:0,
                 from /usr/include/c++/4.8.3/bits/allocator.h:46,
                 from /usr/include/c++/4.8.3/string:41,
                 from /usr/include/c++/4.8.3/bits/locale_classes.h:40,
                 from /usr/include/c++/4.8.3/bits/ios_base.h:41,
                 from /usr/include/c++/4.8.3/ios:42,
                 from /usr/include/c++/4.8.3/ostream:38,
                 from /usr/include/c++/4.8.3/iostream:39,
                 from unionstring2.cc:1:
/usr/include/c++/4.8.3/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = varstruct; _Args = {const varstruct&}; _Tp = varstruct]’:
/usr/include/c++/4.8.3/bits/alloc_traits.h:254:4:   required from ‘static typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = varstruct; _Args = {const varstruct&}; _Alloc = std::allocator<varstruct>; typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type = void]’
/usr/include/c++/4.8.3/bits/alloc_traits.h:393:57:   required from ‘static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = varstruct; _Args = {const varstruct&}; _Alloc = std::allocator<varstruct>; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]’
/usr/include/c++/4.8.3/bits/stl_vector.h:906:34:   required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = varstruct; _Alloc = std::allocator<varstruct>; std::vector<_Tp, _Alloc>::value_type = varstruct]’
unionstring2.cc:34:28:   required from here
/usr/include/c++/4.8.3/ext/new_allocator.h:120:4: error: use of deleted function ‘varstruct::varstruct(const varstruct&)’
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    ^
unionstring2.cc:12:16: note: ‘varstruct::varstruct(const varstruct&)’ is implicitly deleted because the default definition would be ill-formed:
 typedef struct varstruct{
                ^
unionstring2.cc:12:16: error: use of deleted function ‘varstruct::uni::uni(const varstruct::uni&)’
unionstring2.cc:14:19: note: ‘varstruct::uni::uni(const varstruct::uni&)’ is implicitly deleted because the default definition would be ill-formed:
             union uni{
                   ^
unionstring2.cc:17:10: error: union member ‘varstruct::uni::stringVar’ with non-trivial ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
   string stringVar;
          ^
In file included from /usr/include/c++/4.8.3/vector:62:0,
                 from unionstring2.cc:3:
/usr/include/c++/4.8.3/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = varstruct; _Args = {varstruct}]’:
/usr/include/c++/4.8.3/bits/stl_uninitialized.h:75:53:   required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<varstruct*>; _ForwardIterator = varstruct*; bool _TrivialValueTypes = false]’
/usr/include/c++/4.8.3/bits/stl_uninitialized.h:117:41:   required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<varstruct*>; _ForwardIterator = varstruct*]’
/usr/include/c++/4.8.3/bits/stl_uninitialized.h:258:63:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<varstruct*>; _ForwardIterator = varstruct*; _Tp = varstruct]’
/usr/include/c++/4.8.3/bits/stl_uninitialized.h:281:69:   required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = varstruct*; _ForwardIterator = varstruct*; _Allocator = std::allocator<varstruct>]’
/usr/include/c++/4.8.3/bits/vector.tcc:415:43:   required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = {const varstruct&}; _Tp = varstruct; _Alloc = std::allocator<varstruct>]’
/usr/include/c++/4.8.3/bits/stl_vector.h:911:27:   required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = varstruct; _Alloc = std::allocator<varstruct>; std::vector<_Tp, _Alloc>::value_type = varstruct]’
unionstring2.cc:34:28:   required from here
/usr/include/c++/4.8.3/bits/stl_construct.h:75:7: error: use of deleted function ‘varstruct::varstruct(const varstruct&)’
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

还有其他选择吗?

1 个答案:

答案 0 :(得分:1)

根据参考文献,您工会的成员之一是string

  

如果联合包含具有非平凡的非静态数据成员   特殊成员函数(复制/移动构造函数,复制/移动分配,   或析构函数),则默认情况下会在联合中删除该函数,   需要由程序员明确定义。

因此您无法编译,因为在调用vector::push_back的过程中调用了uni的副本构造函数,但是此函数被删除了。如果要编译代码,则需要添加复制构造函数:

uni(const uni& u) {
                new (&stringVar) std::string{u.stringVar};
            }

然后您的代码可以编译甚至可以工作,但是对非平凡类型使用联合并不是一种好方法。您应该在结构中添加type成员,以控制哪种类型的联合处于活动状态。然后,您可以在析构函数中删除正确的成员(对于非平凡类型调用析构函数)。在Bjarne Stroustrup的 C ++编程语言 Anonymous Unions 章中提供了很好的例子。

在结构中具有type成员的代码的修改版本(不是完整代码,只有IDEA)。

enum TYPE {INT,STR,PAGE};

typedef struct varstruct{
        int test;

        union {
            Page page;
            int intVar;
            string stringVar;
        };

        void setPage (Page p) {
            if (type == STR)
                stringVar.~string();
            page = p; 
            type = PAGE;
        }

        void setInt (int i) {
            if (type == STR)
              stringVar.~string();
            intVar = i; 
            type = INT;
        }

        void setString (string s) {
            if (type == STR)
                stringVar = s;
            else 
                new (&stringVar) std::string{s};
            type = STR;
        }

        TYPE type = INT;

        varstruct (const varstruct& v) {
            if (v.type == STR)
                new (&stringVar) std::string{v.stringVar};
            else if (v.type == INT)
                intVar = v.intVar;
            else if (v.type == PAGE)
                page = v.page;
            type = v.type;
        }


        varstruct(){}
        ~varstruct(){
            if (type == STR)
                stringVar.~string();
        }
    } VariableDataStruct;

和main中的代码:

VariableDataStruct structeg;
structeg.test = 1;
structeg.setString("Test");
List.push_back(structeg);
cout<<structeg.stringVar<<endl;