标签: static-initialization

为什么在 gcc 上接受 const 限定变量作为初始值设定项?

在最新版本的 gcc(或 clang)中编译此代码时 -std=c17 -pedantic-errors -Wall -Wextra

static const int y = 1;
static int x = y;
Run Code Online (Sandbox Code Playgroud)

然后我没有收到编译器诊断消息,即使我相当确定这不是有效的 C 而是约束违规。我们可以通过查看C17 6.7.9/4来证明它是不符合的:

约束
...
具有静态或线程存储持续时间的对象的初始值设定项中的所有表达式都应为常量表达式或字符串文字。

然后是关于常量表达式的定义,在这种情况下是整数常量表达式(6.6):

整数常量表达式应具有整数类型,并且只能具有整数常量、枚举常量、字符常量、结果为整数常量的 sizeof 表达式、_Alignof 表达式和作为强制转换的直接操作数的浮点常量的操作数。

最后是关于整数常量的定义(6.4.4.1/2):

整数常量以数字开头,但没有句点或指数部分。它可能有一个指定其基础的前缀和一个指定其类型的后缀。

因此,const int变量不是整数常量,也不是整数常量表达式。因此不是有效的初始化程序。这之前已经讨论过(例如这里),我认为已经确定这是不合格的。但是,我的问题是:

为什么 gcc 即使在严格模式下也选择不合规?

clang 显然一直不合规,但 gcc 从 7.3 版的合规变为 8.0 及更高版本的不合规。即使在没有-pedantic-errors.

似乎已经对这条消息做出了某种积极的、有意识的决定。为什么在 gcc 中完全删除它,为什么在严格模式下编译时不保留它-std=c17 -pedantic-errors

c gcc initializer static-initialization

6
推荐指数
1
解决办法
204
查看次数

为什么 clang 对某些全局变量执行线程安全 init,而对其他全局变量则不然?

inline考虑使用C++ 17 中的新变量功能声明的全局(命名空间范围)变量:

\n
struct something {\n    something();\n    ~something();\n};\n\ninline something global;\n
Run Code Online (Sandbox Code Playgroud)\n

在 x86 上的 Clang 14 中,生成的用于在启动时初始化变量的程序集如下:

\n
__cxx_global_var_init:                  # @__cxx_global_var_init\n        push    rbx\n        mov     al, byte ptr [rip + guard variable for global]\n        test    al, al\n        je      .LBB0_1\n.LBB0_4:\n        pop     rbx\n        ret\n.LBB0_1:\n        mov     edi, offset guard variable for global\n        call    __cxa_guard_acquire\n        test    eax, eax\n        je      .LBB0_4\n        mov     edi, offset global\n        call    something::something() [complete object constructor]\n        mov     edi, offset something::~something() [complete object destructor]\n        mov     esi, offset global\n        mov …
Run Code Online (Sandbox Code Playgroud)

c++ global-variables clang static-initialization c++17

6
推荐指数
0
解决办法
352
查看次数

无法覆盖派生类中的静态初始化

我正在尝试为层次结构中的类提供不同的静态初始化,但是当我尝试使用此代码时:

#include <iostream>

using namespace std;

struct base {
static const char* componentName;
};
const char* base::componentName = "base";

struct derived : public base {};

const char* derived::componentName = "derived";

int main() {

cout << base::componentName << endl;
cout << derived::componentName << endl;
}
Run Code Online (Sandbox Code Playgroud)

我最终得到了这个构建错误:

test.cpp:15: error: ISO C++ does not permit ‘base::componentName’ to be defined as ‘derived::componentName’
test.cpp:15: error: redefinition of ‘const char* base::componentName’
test.cpp:11: error: ‘const char* base::componentName’ previously defined here
Run Code Online (Sandbox Code Playgroud)

似乎静态初始化不能在派生类上重写?如果这不起作用,我可能总是将componentName定义为一个返回const char*的静态函数,唯一的问题是我希望对部分特化进行初始化,并且似乎没有任何方法我知道在部分特化中只重新定义一个函数,而不复制将保持大部分相同的所有其他代码

c++ inheritance static-initialization

5
推荐指数
1
解决办法
4309
查看次数

C++是否可以延迟常量静态成员的初始化?

我使用的是Qt,但这是一个通用的C++问题.我的情况很简单,我有一个Constants具有常量静态成员的类,我希望在进行某些函数调用后对其进行初始化.

Constants.h

#ifndef CONSTANTS_H
#define CONSTANTS_H

class Constants
{
public:

    static const char* const FILE_NAME;
};

#endif // CONSTANTS_H
Run Code Online (Sandbox Code Playgroud)

Constants.cpp

#include "constants.h"
#include <QApplication>

const char* const Constants::FILE_NAME = QApplication::applicationFilePath().toStdString().c_str();
Run Code Online (Sandbox Code Playgroud)

main.cpp中

#include <QtGui/QApplication>
#include "mainwindow.h"
#include "constants.h"
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    qDebug()<< "name: "<<Constants::FILE_NAME;
    //for those who are unfamiliar with Qt, qDebug just prints out
    return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

编译时,我得到:

QCoreApplication :: applicationFilePath:请首先实例化QApplication对象

这里的问题很明显.当在Constants.cpp中调用QApplication的静态函数时,Qt尚未安装QApplication.我需要以某种方式等待直到QApplication a(argc, argv);在main.cpp中传递行

是否有可能,如果没有,你还能建议克服这个问题?

谢谢

c++ qt static-initialization

5
推荐指数
2
解决办法
2748
查看次数

在给定的翻译单元中,文件级静态变量的顺序是否始终相同?

我有一个程序分为两个源文件:

example.cpp

#include <iostream>

class A {
 public:
   A(int x) {
      ::std::cout << "In A(" << x << ")\n";
   }
};

static A first(1);
static A second(2);
Run Code Online (Sandbox Code Playgroud)

例子 __ main.cpp

int main(int argc, const char *argv[])
{
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

该计划的输出是否保证为:

In A(1)
In A(2)
Run Code Online (Sandbox Code Playgroud)

在所有平台和编译器上?如果是这样,它在标准中的位置是这样说的吗?如果我使用名称空间first并且second出现在不同的名称空间中,这是否重要?如果它们不是静态的并且我使用匿名命名空间怎么样?

c++ initialization static-initialization static-order-fiasco

5
推荐指数
1
解决办法
350
查看次数

struct参数的默认值

假设我有以下结构:

struct myStruct
{
 int x;
 int y;
 int z;
 int w;
};
Run Code Online (Sandbox Code Playgroud)

我想在调用以下函数时将此结构初始化为默认值.如果它有助于我正在寻找一个简单的零初始化.

void myFunc(myStruct param={0,0,0,0})
{
 ...
}
Run Code Online (Sandbox Code Playgroud)

但是这段代码给了我编译错误.我试过VS2003和VS2008.

注意:我已经查看了其他提到构造函数使用的答案.但是,我希望用户看到我用于初始化的值.

c++ struct initialization default-value static-initialization

5
推荐指数
2
解决办法
1万
查看次数

C#中静态初始化程序的线程安全性

每个人都说静态初始化程序是线程安全的,但我担心一个特定的细节.

让我说我有

static class MyStaticClass
{
    public static readonly object myField = MyOtherClass.GetNewObject();
}

static class MyOtherClass
{
    public static object GetNewObject()
    { /* arbitrary code that returns a new object */ }
}
Run Code Online (Sandbox Code Playgroud)

C#保证以下哪一项MyStaticClass.myField尚未初始化?

  1. 如果线程1和2尝试一起访问myField(按此顺序),GetNewObject则在线程2读取之前将开始执行myField.

  2. 如果线程1和2尝试一起访问myField(按此顺序),GetNewObject则在线程2读取之前将完成执行myField.

一般来说CLR怎么样:如果它的保证与C#不同,它们在哪些方面有所区别?
在更新版本的.NET框架中是否更改了行为?

注意:

这是一个棘手的问题,我认为完整的答案可能会提到静态构造函数和静态初始化程序之间的区别,以及它们如何交互beforefieldinit以产生声明的结果.

c# multithreading thread-safety static-initialization

5
推荐指数
1
解决办法
1448
查看次数

目标c-局部静态变量初始化线程安全吗?

注意:我使用的是Objective-C ++,其中允许使用非编译时常量(/sf/answers/861337081/

+ (Foo)sharedFoo
{ 
    static Foo *foo = [Foo new];
    return foo;
}
Run Code Online (Sandbox Code Playgroud)

静态初始化程序只能运行一次,但是它是否具有线程安全性,例如,如果多个线程同时调用+(Foo)sharedFoo,是否可以保证[Foo new]仅运行一次?

我问是因为如果这样,那么为什么建议obj-C中的单例模式使用如下所示的dispatch_once呢?

+ (Foo)sharedFoo {
    static Foo *foo = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        foo = [Foo new];
    });

    return foo;
}
Run Code Online (Sandbox Code Playgroud)

我本质上是在问为什么第一行不能只是

static Foo *foo = [Foo new];
Run Code Online (Sandbox Code Playgroud)

如果我们知道静态本地var初始化仅运行一次,则只需完全跳过dispatch_once。

编辑:好的,我找到了答案。1.首先,我意识到我使用的是Objective-C ++,它允许上述代码进行编译(并在运行时运行)2.第二,编译器将该代码转换为不带dispatch_once的单例初始化器的“原始”版本,从而使它确实不是线程安全的。

objective-c objective-c++ static-initialization

5
推荐指数
1
解决办法
727
查看次数

在Windows Phone 8 C#app中不调用静态字段初始值设定项

我有一个静态类,其静态字段已初始化到位:

private static SomeType _instance = new SomeType();
Run Code Online (Sandbox Code Playgroud)

此代码是在多个平台上使用的可移植类库的一部分.在桌面平台上一切正常,但在为Windows Phone 8编译时,_instance为空.但是,如果我将初始化移动到默认的静态构造函数,则_instance会正确初始化.

我试图寻找这种行为的解释,但没有找到任何可以解释它的东西.

更新.我花了一些时间尝试创建一个可重复的步骤序列来重现错误,但在某些时候,即使我切换回原始代码,也不再发生错误.我得出的结论是,这是一个误报,问题显然是由其他原因造成的.离开它没有解释我感到不舒服,但到目前为止,我没有理由相信这与静态字段初始化有关.

c# static-initialization c#-4.0 windows-phone-8

5
推荐指数
1
解决办法
158
查看次数

是否可以保证在std :: string之前初始化指向字符串文字的指针?

//file1.cpp
extern const char* foo;
std::string bar = foo;

//file2.cpp
const char* foo = "foo";
Run Code Online (Sandbox Code Playgroud)

标准保证将bar初始化为"foo"吗?还是可以foo在构造函数中进行设置和段错误之前对其进行初始化,例如SIOF?

c++ static-initialization language-lawyer

5
推荐指数
1
解决办法
104
查看次数