#include <iostream>
#include <string>
class Token {
public:
Token() : tok(INT), ival(0) {}
~Token() {
if (tok == STR) {
sval.~basic_string(); // 联合体中编译器不会自动调用析构函数
}
}
Token& operator=(int i) {
if (tok == STR) {
sval.~basic_string();
}
ival = i;
tok = INT;
return *this;
}
Token& operator=(char c) {
if (tok == STR) {
sval.~basic_string();
}
ival = c;
tok = CHAR;
return *this;
}
Token& operator=(double d) {
if (tok == STR) {
sval.~basic_string();
}
ival = d;
tok = DBL;
return *this;
}
Token& operator=(const std::string& s) {
if (tok == STR) {
sval = s;
}
else {
// 定位 new,在已经分配的内存位置上构造一个对象,而不是在堆上分配新的内存
// 在 sval 的当前位置上构造一个新的 std::string 对象,并使用 s 来初始化它
new(&sval) std::string(s);
}
tok = STR;
return *this;
}
// 赋值运算符(为已存在的对象赋值时被调用)
Token& operator=(const Token& t) {
if (tok == STR && t.tok != STR) {
sval.~basic_string();
}
if (tok == STR && t.tok == STR) {
sval = t.sval;
}
else {
copyUnion(t);
}
tok = t.tok;
return *this;
}
private:
enum {INT, CHAR, DBL, STR} tok;
union {
char cval;
int ival;
double dval;
std::string sval;
};
void copyUnion(const Token& t) {
switch (t.tok)
{
case INT:
ival = t.ival; break;
case CHAR:
cval = t.cval; break;
case DBL:
dval = t.dval; break;
case STR:
new(&sval) std::string(t.sval); break;
}
}
};
int main() {
// 创建 Token 对象
Token t1, t2, t3, t4, t5;
// 使用赋值运算符为对象赋值
t1 = 42; // int
t2 = 'a'; // char
t3 = 3.14; // double
t4 = std::string("Hello, World!"); // std::string
// 输出结果
std::cout << "t1 assigned with int: 42" << std::endl;
std::cout << "t2 assigned with char: 'a'" << std::endl;
std::cout << "t3 assigned with double: 3.14" << std::endl;
std::cout << "t4 assigned with string: \"Hello, World!\"" << std::endl;
// 使用拷贝赋值运算符
t5 = t4;
std::cout << "t5 copied from t4 (which contains a string)" << std::endl;
// 为已包含字符串的 Token 对象赋值一个 int
t4 = 100;
std::cout << "t4 reassigned with int: 100" << std::endl;
return 0;
}
标签:std,string,union,sval,学习,tok,Token,STR
From: https://www.cnblogs.com/hacker-dvd/p/17741245.html