- C++11 FAQ 中文版 - C++11 FAQ
- Stroustrup 先生关于中文版的授权许可邮件
- Stroustrup 先生关于 C++11 FAQ 的一些说明
- 关于 C++11 的一般性的问题
- 您是如何看待 C++11 的?
- 什么时候 C++0x 会成为一部正式的标准呢?
- 编译器何时将会实现 C++11 标准呢?
- 我们何时可以用到新的标准库文件?
- C++0x 将提供何种新的语言特性呢?
- C++11 会提供哪些新的标准库文件呢?
- C++0x 努力要达到的目标有哪些?
- 指导标准委员会的具体设计目标是什么?
- 在哪里可以找到标准委员会的报告?
- 从哪里可以获得有关 C++11 的学术性和技术性的参考资料?
- 还有哪些地方我可以读到关于 C++0x 的资料?
- 有关于 C++11 的视频吗?
- C++0x 难学吗?
- 标准委员会是如何运行的?
- 谁在标准委员会里?
- 实现者应以什么顺序提供 C++11 特性?
- 将会是 C++1x 吗?
- 标准中的"concepts"怎么了?
- 有你不喜欢的 C++特性吗?
- 关于独立的语言特性的问题
- __cplusplus 宏
- alignment(对齐方式)
- 属性(Attributes)
- atomic_operations
- auto – 从初始化中推断数据类型
- C99 功能特性
- 枚举类——具有类域和强类型的枚举
- carries_dependency
- 复制和重新抛出异常
- 常量表达式(constexpr)
- decltype – 推断表达式的数据类型
- 控制默认函数——默认或者禁用
- 控制默认函数——移动(move) 或者复制(copy)
- 委托构造函数(Delegating constructors)
- 并发性动态初始化和析构
- noexcept – 阻止异常的传播与扩散
- 显式转换操作符
- 扩展整型
- 外部模板声明
- 序列 for 循环语句
- 返回值类型后置语法
- 类成员的内部初始化
- 继承的构造函数
- 初始化列表
- 内联命名空间
- Lambda 表达式
- 用作模板参数的局部类型
- long long(长长整数类型)
- 内存模型
- 预防窄转换
- nullptr——空指针标识
- 对重载(override) 的控制: override
- 对重载(override) 的控制:final
- POD
- 原生字符串标识
- 右角括号
- 右值引用
- Simple SFINAE rule
- 静态(编译期)断言 — static_assert
- 模板别名(正式的名称为"template typedef")
- 线程本地化存储 (thread_local)
- unicode 字符
- 统一初始化的语法和语义
- (广义的)联合体
- 用户定义数据标识(User-defined literals)
- 可变参数模板(Variadic Templates)
- 关于标准库的问题
- abandoning_a_process
- 算法方面的改进
- array
- async()
- atomic_operations
- 条件变量(Condition variables)
- 标准库中容器方面的改进
- std::function 和 std::bind
- std::forward_list
- std::future 和 std::promise
- 垃圾回收(应用程序二进制接口)
- 无序容器(unordered containers)
- 锁(locks)
- metaprogramming(元编程)and type traits
- 互斥
- 随机数的产生
- 正则表达式(regular expressions)
- 具有作用域的内存分配器
- 共享资源的智能指针——shared_ptr
- smart pointers
- 线程(thread)
- 时间工具程序
- 标准库中的元组(std::tuple)
- unique_ptr
- weak_ptr
- system error
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
(广义的)联合体
在 C++98(或更早)版本中,union 的成员类型,必须不含自定义构造/析构函数或者赋值操作符。
union U {
int m1;
complex m2; //错误(明显的):complex 拥有构造函数
//错误(不那么明显):string 的内部数据只能严格地由其构造函数,
// 拷贝构造函数,和析构函数去维护
string m3;
};
亦即:
U u; // 使用哪个成员的构造函数呢?
u.m1 = 1; // 给整型成员赋值
string s = u.m3; //灾难:从 string 成员拷贝
显而易见,把值写入一个成员,之后又读取另外一个成员的做法是给自己找麻烦,然而人们往往并非刻意而为(多因失误导致) 。
C++11 对 union 的限制条件进行了放宽,以允许更灵活广泛的成员类型。其中值得特别指出的是,带有自定义构造函数/析构函数的类型现在也可作为 union 的成员了。此外,为使“灵活”不至成为脱缰野马,新标准又特别引入了“第四条军规”(译注:参见下文),并倡导使用“可识别 union”(译注:参见下文 Widget 样例以及 Boost::Any 和 Boost::Variant)。
C++11 中的对 union 的限制条件重新定义如下:
- 不含虚函数(与 C++98 相同)
- 不含引用成员(与 C++98 相同)
- 没有基类(与 C++98 相同)
- 若 union 的某个成员的类型含有自定义构造/拷贝/析构函数,那么该 union 的相应构造/拷贝/析构函数将会被自动“禁用”(译注:在 C++11 中我们可以使用 delete 关键字来“禁用”构造/析构函数),随之而来的后果是:该 union 不能被实例化成对象。(新增的所谓“第四条军规”)
例如:
union U1 {
int m1;
complex m2; // ok
};
union U2 {
int m1;
string m3; // ok
};
上述代码看起来容易出问题(译注:例如有人实例化了 U2 类型的对象并给其 m1 成员赋值之后,当 union 析构时,m3 的析构函数可能会 crash),但是有了第四条军规,刚才的隐含问题便迎刃而解(译注:通过编译错误)。即:
U1 u; // ok
u.m2 = {1,2}; // ok:给 complex 成员赋值
U2 u2; // 编译错误: string 类含有析构函数,因而 U2 的析构函数已被自动禁用
//(译注:析构函数被禁用意味着不允许在栈上实例化 U2 对象,否则无法析构)
U2 u3 = u2; // 编译错误:string 类含有拷贝构造函数,
// 因而 U2 类型同样也不能被拷贝构造
这样看来,先前定义的 U2 几乎没什么实际用途了。唯一可能用到这种奇葩 union 的地方是,把它嵌到结构体里并且额外记录其“当值”成员类型——也就是所谓的“可识别 union”。样例如下:
class Widget { // 用 union 存储的“三态”Widget
private:
// 用以实现“可识别 union”的“当值”类型标记
enum class Tag { point, number, text } type;
union { // 三态的具体存储形式
point p; // point 类含有构造函数
int i;
string s; // string 类含有默认的构造/拷贝/析构函数
};
// ...
// 由于 string 中存在拷贝函数,所以需要“手工拷贝”union
Widget& operator=(const Widget& w)
{
// 译注:从 text 态到 text 态
if (type==Tag::text && w.type==Tag::text) {
s = w.s; // 直接使用 string 的赋值运算符
return *this;
}
// 译注:从 text 态到其他态,意味着 union 不再用于存放 string
// 由于 union 的拷贝函数已被自动禁用,
// 所以需要有人手工释放 string 原先所占资源
if (type==Tag::text) s.~string(); // 此处需要显式析构
switch (w.type) {
case Tag::point: p = w.p; break; // 普通的拷贝
case Tag::number: i = w.i; break;
// 译注:C++98/03 标准中的的原地拷贝构造语法
case Tag::text: new(&s)(w.s); break; // placement new
}
type = w.type;
return *this;
}
};
};
其他参考文献:
- [N2544=08-0054] Alan Talbot, Lois Goldthwaite, Lawrence Crowl, and Jens Maurer: Unrestricted unions (Revison 2)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论