c++ - 在 vector C++14(无限制 union )中的结构内的 union 中创建和存储字符串

标签 c++ c++11 vector

谁能解释一下如何将一个字符串(在一个结构体中的 union 体中)赋值并推送到一个 vector 中?这可能吗? 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)...); }

还有其他选择吗?

最佳答案

根据引用资料,您的 union 成员之一是 string

If a union contains a non-static data member with a non-trivial special member function (copy/move constructor, copy/move assignment, or destructor), that function is deleted by default in the union and needs to be defined explicitly by the programmer.

所以你不能编译,因为在调用vector::push_back 时调用了uni 的复制构造函数,但是这个函数被删除了。如果你想编译你的代码,你需要添加复制构造函数:

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

然后您的代码可以编译甚至可以工作,但是将 union 与非平凡类型一起使用并不是一个好的方法。您应该将 type 成员添加到您的结构中,以控制哪种类型的 union 处于事件状态。然后你可以在析构函数中删除正确的成员(调用非平凡类型的析构函数)。 Bjarne Stroustrup 的书 C++ Programming Language 中的 Anonymous Unions 一章介绍了一个很好的例子。

你的代码的修改版本(它不是完整代码,只有 IDEA),结构中有 type 成员:

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;

关于c++ - 在 vector C++14(无限制 union )中的结构内的 union 中创建和存储字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52316499/

相关文章:

arrays - C++11 段错误试图动态地将数组(<algorithm>)复制到向量中

c++ - 将带有时间戳的 vector 整数连接为 C++ 中的字符串?

c++ - vector 的迭代器---测试结束

c++ - 具有多维 vector 的超立方体

c++ - WINFORM C++ Managed string->unmanaged string 在与 fstream 结合使用时产生意外结果

C++宏导致空指针

c++ - 遍历文本文件并为每一行分配变量

c++ - 回调函数

c++ - 循环流式传输 .ogg 音频 - OpenAL

c++ - std::function 的开销