联盟成员有一个非平凡的拷贝构造函数

21 c++ string constructor

我有一个看起来像这样的联盟:

union {
  int intValue;
  double doubleValue;
  std::string stringValue;
  void *pointerValue;
} values;
Run Code Online (Sandbox Code Playgroud)

当我编译它时,我收到此错误消息(是的,我做了#include <string>):

./Value.hh:19:19: error: union member 'stringValue' has a non-trivial copy constructor                 
      std::string stringValue;                                                                         
                  ^                                                                                    
/Developer/SDKs/MacOSX10.7.sdk//usr/include/c++/4.2.1/bits/basic_string.h:434:7: note: because         
      type 'std::basic_string<char>' has a user-declared copy constructor                              
      basic_string(const basic_string& __str);                                                         
      ^
Run Code Online (Sandbox Code Playgroud)

我使用这个命令编译它:

$ clang++ *.cc -isysroot /Developer/SDKs/MacOSX10.7.sdk/ -shared
Run Code Online (Sandbox Code Playgroud)

我怎样才能std::string在工会中使用?

Nic*_*las 26

你不能.

联合组合了两个功能:存储可能具有选定数量类型的对象的能力,以及在这些类型之间有效(和实现定义)转换的能力.您可以放入一个整数并将其表示视为double.等等.

因为联合必须支持这两种功能(并且由于其他一些原因,例如能够构造一个),因此联合会阻止您执行某些操作.也就是说,您不能在其中放置"实时"对象.任何"生活"足够需要非默认复制构造函数的对象(在许多其他限制中)都不能成为联合的成员.

毕竟,union对象实际上并不具有它实际存储的数据类型的概念.它不存储一种类型的数据; 它同时存储所有这些.你可以钓到正确的类型.那怎么能合理地将一个联盟价值复制到另一个呢?

union的成员必须是POD(普通旧数据)类型.虽然C++ 11确实放松了这些规则,但对象仍然必须具有默认(或其他微不足道的)复制构造函数.并且std::string复制构造函数非常重要.

你可能想要的是一个boost::variant.这是一个可以存储许多可能类型的对象,就像联合一样.然而,与联盟不同,它是类型安全的.因此,它知道联盟中究竟是什么; 因此,它可以复制自身,并且行为类似于常规C++对象.


Man*_*rse 5

你不能把std::string一个联盟.它被C++语言禁止,因为它不安全.考虑到大多数std::string实现都有一个指向某个动态内存的指针,该内存保存字符串的值.还要考虑无法知道哪个工会成员当前处于活动状态.

实现不能调用析构函数std::string,因为它不知道该std::string对象是当前活动的成员,但如果它不调用析构函数,那么内存将被泄露.

  • 我相信在C++ 11中你可以在联合中放置带有非平凡构造函数/析构函数的类型,但是你必须使用placement new和t.~T()语法显式调用它们.9.5.3-9.5.4 (3认同)