头文件中的const变量和静态初始化fiasco [英] const variables in header file and static initialization fiasco

查看:212
本文介绍了头文件中的const变量和静态初始化fiasco的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在阅读了很多有关静态变量初始化的问题后,我仍然不确定这是如何适用于命名空间级别的 const 变量。



在构建脚本生成的文件 config.h 中有以下代码:

  static const std :: string path1 =/ xyz / abc; 
static const std :: string path2 =/ etc;

根据我已经阅读的 static

上面的代码是否倾向于静态初始化fiasco?



如果我在头文件中有以下内容 myclass.h

  class MyClass 
{
public:
MyClass(const std :: string& str):m_str }
std :: string Get()const {return m_str; }

private:
std :: string m_str;
}

const MyClass myclass1(test);

这会造成静态初始化的任何问题吗?



如果我理解正确,由于 const 变量具有内部链接,在这两种情况下应该没有问题?



修改(由于dribeas回答)



也许我应该提及我对以下用例感兴趣:



main.cpp

  #include< config.h> 
#include< myclass.h>

std :: string anotherString(path1 + myclass1.Get());

int main()
{
...
}

关于此用例的另一个问题:在这种情况下,编译器是否会优化掉 path2

解决方案

我试图从C ++ 03标准文档获得必要的信息。这是我发现的:



关于 const static 声明: >

根据在命名空间层定义并声明为 const 的第3.5.3节对象具有内部链接默认。 static 也声明一个命名空间级对象具有内部链接,因此不需要声明一个对象 static const 。 / p>

也根据附件D.2


static关键字的使用

命名空间范围(见3.3.5)中声明对象时弃用。


静态初始化fiasco:



由于变量是在头文件中定义的,所以它们总是在使用它们的任何其他静态对象之前定义。
$ b

从第3.6.2.1节:


具有静态存储持续时间的对象
在命名空间范围中定义在相同的
翻译单元中并且动态地
初始化在
中它们的定义
出现在翻译单元中的顺序。


< blockquote>

答案1:这意味着将传递的变量传递给静态对象引用。

$ b答案2:但是,如果变量是从静态对象的非内联构造函数引用的,则可能会出现问题:



在第3.6.2.1节和第3.6.2.3节中,不同的编译单元中的静态对象都被初始化 if 动态初始化是在<$ c的第一个语句之前完成的请考虑以下内容:

 

code> // consts.h
#include< string>

const std :: string string1 =ham;
const std :: string string2 =cheese;

// myclass.h
#include< string>

class MyClass
{
public:
MyClass();
MyClass(s​​td :: string str);
std :: string Get(){return memberString; }
private:
std :: string memberString;
}

// myclass.cpp
#includeconsts.h
#includemyclass.h

MyClass: :MyClass():memberString(string1){}

MyClass :: MyClass(s​​td :: string str):memberString(str){}

// main.cpp
#include< iostream>
#includeconsts.h
#includemyclass.h

MyClass myObject1;
MyClass myObject2(string2);

using namespace std;

int main()
{
cout< myObject1.Get(); //可能不打印ham
cout<< myObject2.Get(); //将始终打印cheese
}

由于 myclass .cpp 有自己的 const 变量副本,这些可能不会被初始化 MyClass :: MyClass / code>被调用。



所以,在头文件中定义的 const 以一种易于产生静态初始化的方式使用fiasco



据我所见,这只适用于不需要静态初始化的变量: / p>

从C ++ 03标准,第3.6.2.1节:


使用静态
存储时间的POD类型(3.9)用
初始化常量表达式(5.19)将
初始化之前,任何动态
初始化发生。



After reading a lot of the questions regarding initialization of static variables I am still not sure how this applies to const variables at namespace level.

I have kind of the following code in a header file config.h generated by the build script:

static const std::string path1 = "/xyz/abc";
static const std::string path2 = "/etc";

According to what I have read the static keyword is not necessary, even deprecated here.

My Question: Is the code above prone to the static initialization fiasco?

If I have the following in a header file myclass.h:

class MyClass
{
public:
    MyClass(const std::string& str) : m_str(str) {}
    std::string Get() const { return m_str; }

private:
    std::string m_str;
}

const MyClass myclass1("test");

Will this pose any problems with static initialization?

If I understood right, due to const variables having internal linkage there should be no problem in both cases?

Edit: (due to dribeas answer)

Maybe I should mention that I am interested in use cases like:

In main.cpp:

#include <config.h>
#include <myclass.h>

std::string anotherString(path1 + myclass1.Get());

int main()
{
    ...
}

Another question regarding this use case: Will the compiler optimize away path2 in this case?

解决方案

I tried to get the necessary information right from the C++03 Standard document. Here is what I found:

Regarding the const static declarations:

According to section 3.5.3 objects defined at namespace level and declared const have internal linkage by default. static also declares a namespace level object to have internal linkage so there is no need to declare an object static const.

Also according to Annex D.2

The use of the static keyword is deprecated when declaring objects in namespace scope (see 3.3.5).

Regarding the static initialization fiasco:

Since the variables are defined in a header file they are always defined before any other static objects using them.

From section 3.6.2.1:

Objects with static storage duration defined in namespace scope in the same translation unit and dynamically initialized shall be initialized in the order in which their definition appears in the translation unit.

Answer 1: This means passing the variables to a static object constuctor should be fine.

Answer 2: However a problem could occur if the variables are referenced from a non-inline constructor of a static object:

Neither in section 3.6.2.1 nor 3.6.2.3 is it specified in which order the static objects in different compilation units are initialized if dynamic initialization is done before the first statement of main.

Consider the following:

// consts.h
#include <string>

const std::string string1 = "ham";
const std::string string2 = "cheese";

// myclass.h
#include <string>

class MyClass
{
public:
    MyClass();
    MyClass(std::string str);
    std::string Get() { return memberString; }
private:
    std::string memberString;
}

// myclass.cpp
#include "consts.h"
#include "myclass.h"

MyClass::MyClass() : memberString(string1) {}

MyClass::MyClass(std::string str) : memberString(str) {}

// main.cpp
#include <iostream>
#include "consts.h"
#include "myclass.h"

MyClass myObject1;
MyClass myObject2(string2);

using namespace std;

int main()
{
    cout << myObject1.Get(); // might not print "ham"
    cout << myObject2.Get(); // will always print "cheese"
}

Since myclass.cpp has its own copy of the const variables, these might not be initialized when MyClass::MyClass() is called.

So yes, const variables defined in header files can be used in a way that is prone to the static initialization fiasco

As far as I can see this does only apply to variables not requiring static initialization:

From C++03 standard, section 3.6.2.1:

Objects of POD types (3.9) with static storage duration initialized with constant expressions (5.19) shall be initialized before any dynamic initialization takes place.

这篇关于头文件中的const变量和静态初始化fiasco的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆