placement new显式构造报错及C++ union相关命名空间疑问求助
解决你的C++隐式Union编译错误与析构函数命名空间疑问
咱们先搞定你碰到的placement new编译错误:
你代码里的这行写法完全不对:
new(&str)(s.str);
(哪怕是你写的new(&str){s.str};也有问题)
placement new的标准语法是new (内存地址) 要构造的类型(构造参数)——你漏掉了关键的类型名std::string!编译器根本不知道你要在&str指向的内存块上构造什么对象,所以才会报s未定义、缺少)的错误。正确的写法应该是:
new(&str) std::string(s.str);
接下来聊你关于析构函数调用与命名空间的疑问:
你觉得必须加using namespace std;才能调用str.~string();,其实问题根源不在析构函数的调用语法,而是你union里的成员声明。
- 如果你去掉
using namespace std;,首先你的union里string str;这一行就会编译失败——因为string是std::string的简写,编译器不知道这个未加前缀的string是什么。你得先把union成员改成std::string str;,才能在没有using namespace std;的情况下让代码通过编译。 - 当你把成员改成
std::string str;后,完全可以直接调用str.~std::string();,这是完全合法的语法。你试的str.std::~string();是错误的写法,析构函数的调用规则是对象.~类型(),这里的类型必须是对象静态类型的完整名称,所以正确写法就是str.~std::string();。
你之前尝试str.~std::string();失败,大概率是因为你没同步把union里的string改成std::string,导致str的类型不被识别,进而析构函数调用也报错。
另外提个小细节:你的代码里同时有type(public)和stored(private)两个枚举成员,这显然是冗余的,会导致逻辑不一致,建议只保留一个来跟踪当前union存储的类型。
最后给你贴个修正后的完整operator=版本(去掉冗余成员,调整placement new写法,无需using namespace std;):
#include <string> class MemoryObject { public: enum class Type { STRING, BOOLEAN }; Type type; MemoryObject& operator=(const MemoryObject& s) { // 先析构当前对象的string(如果当前类型是STRING) if (type == Type::STRING) { str.~std::string(); } type = s.type; switch (s.type) { case Type::BOOLEAN: boolean = s.boolean; break; case Type::STRING: new(&str) std::string(s.str); // 正确的placement new语法 break; default: break; } return *this; } private: union { unsigned long boolean; std::string str; // 显式使用std::string,无需引入整个std命名空间 }; };
这样修改后,代码就能正常编译运行,也不用依赖using namespace std;了。
内容的提问来源于stack exchange,提问作者jackb
相关产品推荐
相关产品推荐

