联合字符串,段错误

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);
}