gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 04:56:52 28 4
gpt4 key购买 nike

谁能解释一下如何将一个字符串(在一个结构体中的 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/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com