【问题标题】:Static structure initialization with tags in C++在 C++ 中使用标签进行静态结构初始化
【发布时间】:2011-08-13 00:42:11
【问题描述】:

我已经在 stackoverflow 中搜索了答案,但找不到相关内容。

我正在尝试通过指定它们的标签来初始化具有初始值的静态结构实例,但在编译时出现错误:

src/version.cpp:10: error: expected primary-expression before ‘.’ token

代码如下:

// h
typedef struct
{
    int lots_of_ints;
    /* ... lots of other members */
    const char *build_date;
    const char *build_version;
} infos;

还有错误代码:

// C

static const char *version_date = VERSION_DATE;
static const char *version_rev  = VERSION_REVISION;

static const infos s_infos =
{
   .build_date    = version_date, // why is this wrong? it works in C!
   .build_version = version_rev
};

const infos *get_info()
{
    return &s_infos;
}

所以基本思路是绕过“其他成员”初始化,只设置相关的build_datebuild_version值。 这曾经在 C 中工作,但我不知道为什么它不能在 C++ 中工作。

有什么想法吗?

编辑

我意识到这段代码看起来像简单的 C,实际上它是。整个项目都是 C++,所以我必须使用 C++ 文件扩展名来防止 makefile 依赖混乱(%.o: %.cpp

【问题讨论】:

  • 为什么会这样?它适用于 C! 主要是因为 C 和 C++ 是不同的语言。
  • @David - 但有足够多的共同点,一个源于另一个,并且不断分享想法,因此对混乱感到压力是不公平的。 C99 的某些部分已经导入到 C++0x 中,例如“long long”。
  • @Steve314:不要误会我的意思,我并没有因为混乱而感到压力(我根本没有压力),但问题中没有混乱:他知道他们是不同的语言!当人们说因为一个特性在 C 中工作它必须 在 C++ 中工作时,我觉得很有趣。考虑一下这个,或者void f( int x ) { int array[x]; ...} 它们是不同的语言,虽然它们有着共同的过去,但它们并不总是共享未来。
  • 我明白你的意思,我完全理解它们是不同语言的事实。事情是,我虽然这个微不足道的东西也可以在 C++ 中实现。据我所知,这是设置静态结构的一种非常优雅的方式。另一方面,我也同意这不是一种非常“C++”的使用结构的方式:我应该有一个构造函数。

标签: c++ static tags struct initialization


【解决方案1】:

我相信这是在 C99 中添加的一项功能,但从未成为 C++ 中的标准功能。

但是,一些编译器可能将其作为非标准语言扩展提供。

【讨论】:

    【解决方案2】:

    您使用的功能是 C99 功能,并且您使用的 C++ 编译器不支持它。请记住,尽管 C 代码通常是有效的 C++ 代码,但 C99 代码并非总是如此。

    【讨论】:

    • 再解释一下——虽然 C++ 最初的目标是向后兼容 C,但从长远来看保持“横向”兼容性并不一定有意义。用 C 编写但从 C++ 调用的代码对两者来说都是一种痛苦——接口不符合 C++ 约定,但它对 C 编译器施加了约束和开销(例如,通过 C 函数传播异常),这让一些 C 人大吃一惊。
    【解决方案3】:

    以下示例代码以我认为更 C++ 的方式定义了一个结构(不需要 typedef),并使用构造函数来解决您的问题:

    #include <iostream>
    
    #define VERSION_DATE "TODAY"
    #define VERSION_REVISION "0.0.1a"
    
    struct infos {
        int lots_of_ints;
        /* ... lots of other members */
        const char *build_date;
        const char *build_version;
    
        infos() : 
            build_date(VERSION_DATE), 
            build_version(VERSION_REVISION) 
        {} 
    };
    
    static const infos s_infos;
    
    const infos *get_info()
    {
        return &s_infos;
    }
    
    int main() {
    
        std::cout << get_info()->build_date << std::endl;
        std::cout << get_info()->build_version << std::endl;
    
        return 0;
    }
    

    【讨论】:

    • 这种初始化方式的运行时开销在 C99 版本中不存在,至少在原则上是这样,尽管它通常不会是很大的开销,我不会感到惊讶如果某些编译器在某些情况下可以优化初始化,有效地给出与 C99 语法相同的结果。在这种情况下,它只需要函数内联和常量表达式的编译时评估来处理它。
    • @Steve - 是的,但它具有有效 C++ 的优势,所以在我的书中这是一个加号(加号)! :)
    • 虽然我喜欢这样,但运行时开销并不是我想要的。我将坚持老式的“成熟”静态定义。无论如何谢谢:)
    猜你喜欢
    • 2023-04-05
    • 1970-01-01
    • 2011-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多