【问题标题】:g++ warning when using optional 'struct' keyword使用可选的“结构”关键字时的 g++ 警告
【发布时间】:2011-06-01 20:52:05
【问题描述】:

如果我写这个程序:

#include <iostream>

namespace foo {
    struct bar {
        int x;
    };
}

int main (void) {
    struct foo::bar *a = new struct foo::bar;
    delete a;
    return 0;
}

并编译它:

g++ main.cxx -Wall -Wextra

它给了我这个警告:

main.cxx: In function ‘int main()’:
main.cxx:10:39: warning: declaration ‘struct foo::bar’ does not declare anything [enabled by default]

但是,如果我在 new 关键字之后取出 struct 关键字:

#include <iostream>

namespace foo {
    struct bar {
        int x;
    };
}

int main (void) {
    struct foo::bar *a = new foo::bar;
    delete a;
    return 0;
}

并以同样的方式编译它,g++ 不会输出任何警告。如果我使用 struct 关键字,为什么 g++ 会输出该警告?

【问题讨论】:

  • 有趣的是,clang++ 和 comeau 都没有抱怨语法,粗略地看一下标准 (C++03) 也无助于理解问题。
  • 因为这只是一个警告,所以我不敢说是错误——而是一个 GCC 错误?代码对我来说看起来不错。此外,它与命名空间相关——在没有命名空间的情况下做同样的事情不会产生警告。

标签: c++ namespaces struct g++ compiler-warnings


【解决方案1】:

在 C++ 中,struct 关键字定义了一个类型,新类型不再需要 struct 关键字。这是 C 和 C++ 之间的众多差异之一。

【讨论】:

  • 这解释了为什么后面的代码可以工作,但不能解释为什么第一个代码会产生警告。
  • 我理解C++中不需要使用关键字;我说它在线程标题中是可选的。不过感谢您的回复。
  • 是可选的吗?标准对此有何规定?
  • According to MSDN,struct 关键字是“一旦定义了类型就不需要了”。这就是我的意思,所以如果我模棱两可,我深表歉意。
【解决方案2】:

检查错误:

main.cxx:10:39: 警告:声明 ‘struct foo::bar’ 没有声明任何内容[默认启用]

g++ 认为您正在声明一个名为 foo::bar 的新 struct,而不是分配 struct foo::bar 类型的内存。我的猜测是因为 g++ 假定任何不声明左值的 struct 的使用都是为了声明类型。

【讨论】:

  • 我明白你的意思,但如果编译器正在考虑正在声明一个新类型,那么它应该以一个错误退出,而不是产生一个简单的警告,因为标准明确指出你无法在新表达式中声明新类型
  • @Adetque 最好等待至少 24 小时后再接受答复,以便其他人有机会回复。在这种情况下,我认为您接受的答案是错误的。
  • @David:也许我们应该高兴的是 g++ 正在惩罚将 C++ 视为 C-with-classes 的用户。 ;-P
  • @Neil Butterworth:好的,我一定会这样做的。 @ildjarn:我尽量避免那样对待它。这只是我从 C 那里得到的一个习惯。
【解决方案3】:

只是为了发布能说明问题和不能说明问题的最少代码:

namespace N {
struct A {};
}

struct B {};

int main() {
    struct N::A * a  = new struct N::A; // problem
    struct B * b  = new struct B;       // ok
}

就我个人而言,我认为这是一个小的 GCC 错误,但我对命名空间的无数种方式并不明智。

【讨论】:

    【解决方案4】:

    注意:

       struct foo::bar *a = new struct foo::bar;
    // ^^^^^^ (1)
                            //  ^^^^^^ (2)
    
    1. 在 C++ 中不需要
      • 将结构放在这里是 C 的后遗症,在 C++ 中不再需要
        因为所有类型都在同一个namespace.
        而在 C 结构中,有自己的命名空间,与其他类型分开。
        允许保留与 C 的向后兼容性。
    2. 这里的结构看起来像是在向前声明一些东西。

    在 C++ 中,上面写成:

       foo::bar* a = new foo::bar;
    

    //或者最好

       foo::bar* a = new foo::bar(); // This makes a difference if you don't define
                                     // a default constructor.
    

    来自大卫(下)

    足够重要,我认为它需要在答案中而不是在 cmets 中:

    namespace foo
    {
        struct bar {};
        void bar() {}
    }
    
    int main()
    {
        struct foo::bar* p = new struct foo::bar;
        // Needed here because the compiler can't tell the difference between
        // a struct and a function otherwise
    }
    

    【讨论】:

    • 1.在 C++ 中不需要,或者不需要,取决于代码的其余部分:namespace foo { struct bar {}; void bar() {} } int main() { struct foo:bar* p = new struct foo::bar; }。在那个特别复杂的例子中,在 C++ 中需要使用struct 来告诉编译器在命名空间foo 中搜索bar,但只能在用户定义的类型集中——并避免使用其他类型的标识符,比如函数或变量。
    猜你喜欢
    • 2018-09-04
    • 2014-07-29
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    相关资源
    最近更新 更多