联合字符串,段错误
String in union, segfault
这基本上是一个标记联合:
#include <string>
using std::string;
struct test{
test():tag(INT),i(0){};
test(const test&)=delete;
test& operator=(const test&)=delete;
enum {STRING,INT} tag;
union {
string s;
int i;
};
test& operator=(string s){
this->s=s;
tag=STRING;
return *this;
}
test& operator=(int i){
this->i=i;
tag=INT;
return *this;
}
~test(){
if (tag==STRING)
s.~string();
}
};
int main(){
test instance;
instance="string";
return 0;
}
它可以编译,但每次都会因分段错误而崩溃。我只是出于好奇,它是一个非常完整的联合 class,提供了一个自定义析构函数,没有移动也没有复制,那么为什么会崩溃?我必须在联合中使用 string*
吗?如果是,为什么?
仔细阅读 C++11 中的 rule of five
这是错误的代码:
/// wrong code
test& operator=(string s){
this->s=s;
tag=STRING;
return *this;
}
因为您在分配之前错误地假设 this->s
有效。您应该使用 构造 的 placement new (在从 &this->s
开始的 未初始化 内存区域中):
test& operator=(string ss){
if (tag==STRING) { s=ss; return *this; }
new((void*)&s) std::string(ss);
tag=STRING;
return *this;
}
顺便说一句,我想你也应该明确地 define
test(const test&s);
test(const std::string&);
test& operator=(const test&);
test(test&&s);
test& operator=(test&&);
顺便说一句,您显然缺少构造函数:
test(const std::string&str) {
tag = STRING;
new ((void*)(&s)) std::string(str);
}
这基本上是一个标记联合:
#include <string>
using std::string;
struct test{
test():tag(INT),i(0){};
test(const test&)=delete;
test& operator=(const test&)=delete;
enum {STRING,INT} tag;
union {
string s;
int i;
};
test& operator=(string s){
this->s=s;
tag=STRING;
return *this;
}
test& operator=(int i){
this->i=i;
tag=INT;
return *this;
}
~test(){
if (tag==STRING)
s.~string();
}
};
int main(){
test instance;
instance="string";
return 0;
}
它可以编译,但每次都会因分段错误而崩溃。我只是出于好奇,它是一个非常完整的联合 class,提供了一个自定义析构函数,没有移动也没有复制,那么为什么会崩溃?我必须在联合中使用 string*
吗?如果是,为什么?
仔细阅读 C++11 中的 rule of five
这是错误的代码:
/// wrong code test& operator=(string s){ this->s=s; tag=STRING; return *this; }
因为您在分配之前错误地假设 this->s
有效。您应该使用 构造 的 placement new (在从 &this->s
开始的 未初始化 内存区域中):
test& operator=(string ss){
if (tag==STRING) { s=ss; return *this; }
new((void*)&s) std::string(ss);
tag=STRING;
return *this;
}
顺便说一句,我想你也应该明确地 define
test(const test&s);
test(const std::string&);
test& operator=(const test&);
test(test&&s);
test& operator=(test&&);
顺便说一句,您显然缺少构造函数:
test(const std::string&str) {
tag = STRING;
new ((void*)(&s)) std::string(str);
}