无限制的并集是否需要放置new和构造函数定义? [英] Do unrestricted unions require placement new and a constructor definition?

查看:110
本文介绍了无限制的并集是否需要放置new和构造函数定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到的无限制联合的示例在构造时总是使用new放置。 Wikipedia中有关C ++ 11功能的文章在联合的构造函数中使用了新的放置。

The examples I've seen of unrestricted unions always seem to use placement new when constructing. The Wikipedia article for C++11 features uses placement new in the constructor of a union.

https://en.wikipedia.org/wiki/C%2B%2B11#Unrestricted_unions

#include <new> // Required for placement 'new'.

struct Point {
    Point() {}
    Point(int x, int y): x_(x), y_(y) {} 
    int x_, y_;
};

union U {
    int z;
    double w;
    Point p; // Illegal in C++03; legal in C++11.
    U() {new(&p) Point();} // Due to the Point member, a constructor definition is now required.
};

是否需要在此处使用新的展示位置?例如,这段代码在不使用gcc和valgrind发出警告的情况下进行编译,而在使用联合存储字符串时没有显示内存泄漏:

Is it necessary to use placement new here? For example, this piece of code compiles without warnings with gcc and valgrind shows no memory leaks when the union is used to hold a string:

struct HasUnresUnion
{
    enum { Int, String } tag;

    HasUnresUnion(int i)
      : tag(Int),
        as_int(i)
    {}

    HasUnresUnion(std::string str)
      : tag(String),
        as_str(std::move(str))
    {}

    ~HasUnresUnion()
    {
        using std::string;
        if (tag == String)
            as_str.~string();
    }

    union
    {
        int as_int;
        std::string as_str;
    };
};

这里似乎没有任何歧义,所以我不明白为什么该标准会取缔这个。这是法律法规吗?联合被未初始化(而不是被分配给)时,是否需要新的放置位置?工会中的建设者是必需的吗?我肯定见过没有自己的构造函数的不受限制的联合,但是Wikipedia明确声明了它是必需的。

It doesn't seem like there's any ambiguity here so I don't see why the standard would outlaw this. Is this legal code? Is placement new necessary when the union is uninitialized (rather than being assigned to)? Is the constructor in the union required? I've definitely seen unrestricted unions without their own constructors but Wikipedia explicitly states it's required.

推荐答案

简介



您显示的摘录非常安全;法律上允许您在初始化类工会类时初始化一个非静态数据成员。

Introduction

The snippet you have shown is perfectly safe; you are legally allowed to initialize one non-static data-member when initializing your union-like class.

维基百科文章中有一个示例,其中使用了 placement-new ,因为他们正在写

The wikipedia article has an example where placement-new is used because they are writing to a member after the point in which it is possible to directly initialize a certain member.

union A {
   A () { new (&s1) std::string ("hello world"); }
  ~A () { s1.~basic_string<char> (); }
  int         n1;
  std::string s1;
};

但是,上一个代码片段在语义上等效于以下内容,其中我们明确指出 A :: s1 在构造 A 时应初始化。

The previous snippet is however semantically equivalent to the following, where we explicitly state that A::s1 shall be initialized when constructing A.

union A {
   A () : s1 ("hello world") { }
  ~A () { s1.~basic_string<char> (); }
  int         n1;
  std::string s1;
};






阐述



在您的代码段中,您的类中有一个匿名联合(这使您的类成为类工会类),这意味着除非您初始化<在初始化类—时,联盟的一个强成员您必须稍后使用 placement-new 对其进行初始化。


Elaboration

In your snippet you have an anonymous union inside your class (which makes your class a union-like class), which means that unless you initialize one of the members of the union during initialization of the class — you must use placement-new to initialize them at a later time.


9.5/1 -- Unions -- [class.union]p1




在一个联合中,最多有一个非静态数据成员可以在
的任何时间处于活动状态,也就是说,最多可以将
的最多一个非静态数据成员的值随时存储在联合中。

In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.





3.8/1 -- Object lifetime -- [basic.life]p1




[...]


类型为 T 的对象的生存期始于以下时间:

[...]

The lifetime of an object of type T begins when:

    $获得类型正确的对齐方式和大小为 T 的b $ b
  • 存储,以及

  • (如果对象具有非简单的初始化,它的初始化已经完成。

  • storage with the proper alignment and size for type T is obtained, and
  • if the object has non-trivial initialization, its initialization is complete.

类型为 T 的对象的生存期在以下时间结束:

The lifetime of an object of type T ends when:


  • 如果 T 是具有非平凡析构函数的类类型(12.4),则析构函数调用开始,或者

  • 对象占用的存储空间被重用或释放。

  • if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or
  • the storage which the object occupies is reused or released.


这篇关于无限制的并集是否需要放置new和构造函数定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆