c++ - union 成员可能没有构造函数,但是 `std::pair` 可以吗?

标签 c++ constructor unions std-pair

union成员可能没有析构函数或构造函数。所以我不能模板化以下类 Foo靠我自己MyClass如果MyClass有一个构造函数:

template<class T>
struct Foo {
  T val;
  Foo(T val_) : val(val_) {}
  size_t hash() const {
    union {T f; size_t s;} u = { val };
    return u.s;
  }
};
struct MyClass {
  bool a;
  double b;
  MyClass(bool a_, double b_) : a(a_), b(b_) {}
};

如果我这样做,我会得到这个错误:

member 'MyClass Foo<T>::hash() const 
[with T = MyClass]::<anonymous union>::f' with constructor 
not allowed in union

为了解决这个问题,我创建了 MyClass有一个笨拙的构造函数,它首先复制周围的东西:

struct MyClass {
  bool a;
  double b;
};
MyClass createMyClass(bool a, double b) {
  MyClass m;
  m.a = a;
  m.b = b;
  return m;
}

但我想知道是否有比使用这个 createMyClass 更好的方法功能。构造函数会更有效,并且作为关键组件 MyClassFoo<MyClass>在我的代码中构造了数百万次。

标准::对

我也有点惊讶它可以使用std::pairunion :

Foo<std::pair<bool, double> > f2(std::make_pair(true, 3.12));

据我所知,std::pair ( see code ) 有一个构造函数?

最佳答案

编辑:我最初对std::pair 的立场是错误的,它不应该被允许出现在 union 中。对于要成为 union 的有效成员的类,它必须具有符合标准 9.5.1 的普通构造函数。普通构造函数的定义是这样的,来自第 12.1.5 段:

If there is no user-declared constructor for class X, a default constructor is implicitly declared. An implicitly-declared default constructor is an inline public member of its class. A constructor is trivial if it is an implicitly-declared default constructor and if:

  • its class has no virtual functions and no virtual base classes, and
  • all the direct base classes of its class have trivial constructors, and
  • for all the nonstatic data members of its class that are of class type (or array thereof), each such class has a trivial constructor

第 20.2.2.2 段声明以下构造函数必须成对可用:

pair(const T1& x, const T2& y);

只要提供此构造函数,就不会隐式声明任何默认构造函数。

有趣的是,我的编译器 (Visual Studio 2008) 似乎给予 std::pair 特殊待遇。如果我从 std::pair 实现中复制代码并将其放在我自己的命名空间 foo 中, union 将不起作用:)

namespace foo {
    template<class _Ty1, class _Ty2> struct pair {
        typedef _Ty1 first_type;
        typedef _Ty2 second_type;
        pair() : first(_Ty1()), second(_Ty2()) {
        }
    }
}

//This doesn't work in VC2008
union Baz {
    foo::pair<bool, double> a;
    int b;
}
//This works in VC2008
union Buz {
    std::pair<bool, double> a;
    int b;
}

您的解决方案是解决此问题的常用方法。我通常在类名前加上 C(construct 的缩写)以部分模仿普通的构造函数语法,在您的情况下这将变为 CMyClass(a, b)

正如 Steve 和 Matthieu 所指出的,您没有使用非常好的哈希函数。首先,并不能真正保证(我认为,如果我错了请纠正我) union 体中的 fs 甚至会部分占用相同的内存空间,其次即使他们在实践中可能会共享第一个 min(sizeof(s), sizeof(f)) 字节,这意味着对于 MyClass 你只是部分散列的值(value)。在这种情况下,您将对 bool a 的值进行哈希处理,在这种情况下有两个选项:

  1. 您的编译器使用 int 作为 bool 的内部表示,在这种情况下,您的哈希函数将只返回两个值,一个为真,一个为假。<
  2. 您的编译器使用char 作为bool 的内部表示。在这种情况下,该值可能会被填充到至少 sizeof(int),或者用零填充,在这种情况下,您的情况与 1 相同。或者在 时使用堆栈上的任何随机数据>MyClass 已分配,这意味着您将获得相同输入的随机哈希值。

如果您需要对 T 的整个值进行散列,我会像 Steve 建议的那样将数据复制到一个临时缓冲区中,然后使用讨论的可变长度散列函数之一 here .

关于c++ - union 成员可能没有构造函数,但是 `std::pair` 可以吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1888293/

相关文章:

c++ - C 中特定的 toSquare 函数

c++ - 如何通过cout将字符输出为整数?

constructor - 无法编译内部构造函数调用原因 :Primary constructor call expected

C和 Bison : pointers to struct in %union definition

c - 声明 union 类型变量

c++ - 分配给成员(member) union

c++ - vs2015 cuda9.0 链接 SHA1_Init 与 CUDA 实现而不是 openssl cpu 库

C++正则表达式从文件路径获取文件夹

iphone - 在 iPhone 应用程序中使用 C++ 结构

delphi - 为什么我在 IDE 中得到了另一个尺寸的组件?