谁能解释一下如何将一个字符串(在结构内部的并集中)分配并推入向量中?这可能吗?引导程序是否试图访问无效的内存?
#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)...); }
还有其他选择吗?
答案 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;