101

一些 C++ 编译器允许匿名联合和结构作为标准 C++ 的扩展。这是一些语法糖,偶尔会很有帮助。

阻止它成为标准一部分的理由是什么?有技术障碍吗?一个哲学的?或者只是不足以证明它的合理性?

这是我正在谈论的示例:

struct vector3 {
  union {
    struct {
      float x;
      float y;
      float z;
    };
    float v[3];
  };
};

我的编译器会接受这一点,但它警告说“无名结构/联合”是 C++ 的非标准扩展

4

6 回答 6

59

正如其他人指出的那样,标准 C++ 中允许使用匿名联合,但不允许使用匿名结构。

原因是 C 支持匿名联合但不支持匿名结构*,因此 C++ 支持前者是为了兼容,但不支持后者,因为它不需要兼容性。

此外,在 C++ 中匿名结构并没有多大用处。您演示的用途是拥有一个包含三个浮点数的结构,这些浮点数可以由.v[i].x.y、 和引用.z,我相信会导致 C++ 中的未定义行为。C++ 不允许您写入联合的一个成员,例如.v[1],然后从另一个成员读取,例如.y。尽管这样做的代码并不少见,但实际上并没有很好地定义。

C++ 的用户定义类型工具提供了替代解决方案。例如:

struct vector3 {
  float v[3];
  float &operator[] (int i) { return v[i]; }
  float &x() { return v[0]; }
  float &y() { return v[1]; }
  float &z() { return v[2]; }
};

* C11 显然添加了匿名结构,因此未来对 C++ 的修订可能会添加它们。

于 2012-10-08T16:07:19.290 回答
25

我会说,您vector3只需使用union

union vector3 {
  struct { float x, y, z; } ;
  float v[3] ;
} ;

当然,匿名结构一个 MSVC 扩展。但是现在 ISO C11 允许了,gcc 也允许了,Apple 的 llvm 编译器也允许了。

为什么在 C11 而不是 C++11 中?我不确定,但实际上大多数(gcc++、MSVC++ 和 Apple 的 C++ 编译器)C++ 编译器都支持它们。

于 2012-10-15T19:14:43.157 回答
5

不明白你的意思。C++ 规范的第 9.5 节,第 2 节:

形式的联合

union { member-specification } ;

称为匿名联合;它定义了一个未命名类型的未命名对象。

你也可以这样做:

void foo()
{
  typedef
  struct { // unnamed, is that what you mean by anonymous?
    int a;
    char b;
  } MyStructType; // this is more of a "C" style, but valid C++ nonetheless

  struct { // an anonymous struct, not even typedef'd
    double x;
    double y;
  } point = { 1.0, 3.4 };
}

并不总是很有用......虽然有时在讨厌的宏定义中很有用。

于 2010-02-12T18:03:35.733 回答
1

工会可以是匿名的;参见标准 9.5 第 2 段。

您认为匿名结构或类的目的是什么?在推测为什么某些东西不在标准中之前,我想知道为什么它应该是,而且我没有看到匿名结构的用途。

于 2010-02-12T18:06:41.220 回答
1

根据编辑、评论和这篇 MSDN 文章:匿名结构,我会冒险猜测 - 它与封装的概念不符。除了添加一个成员之外,我不希望一个类的成员会弄乱我的类命名空间。此外,对匿名结构的更改可能会在未经许可的情况下影响我的班级。

于 2010-02-13T03:12:37.813 回答
0

你的代码

union {
  struct {
    float x;
    float y;
    float z;
  };
  float v[3];
};

就好像

union Foo {
   int;
   float v[3];
};

这肯定是无效的(在 C99 及之前的版本中)。

原因可能是为了简化解析(在 C 中),因为在这种情况下,您只需要检查 struct/union 主体是否只有“声明符语句”,例如

Type field;

也就是说,gcc 和“其他编译器”支持未命名字段作为扩展。

编辑: C11(§6.7.2.1/13)现在正式支持匿名结构。

于 2010-02-12T21:03:31.927 回答