extern如何在命名空间中工作? [英] How does extern work in namespaces?

查看:471
本文介绍了extern如何在命名空间中工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行一个简单的程序,类似于我在此处一>。当在多个文件中包含常量时,它旨在减少代码膨胀。它通过在名称空间内使用各自的常量全局变量以及它们各自的 extern 前向声明来实现这一点。



全局变量.h

  #ifndef GLOBALS_H_ 
#define GLOBALS_H_

名称空间常量
{
//只转发声明
extern const double pi;
extern const double avogadro;
extern const double my_gravity;
}

#endif



globals.cpp

  namespace常量
{
//实际全局变量
extern const双pi(3.14159);
extern const double avogadro(6.0221413e23);
extern const double my_gravity(9.2); // m / s ^ 2 - 地球上的引力很小
}

source.cpp

  #include< iostream> 
#include< limits>

#includeglobals.h

int main()
{
double value_of_pi =常量:: pi;

std :: cout<< value_of_pi;

std :: cin.clear();
std :: cin.ignore(std :: numeric_limits< std :: streamsize> :: max(),'\\\
');
std :: cin.get();

返回0;
}

我假设Constants :: pi获取全局变量中包含的值pi。 cpp Constants命名空间,并且可以这样做,因为它可以从包含的globals.h中访问命名空间本身。我不明白为什么globals.cpp中的 const全局定义/初始化 需要 extern 关键字?我尝试删除globals.cpp中的 extern 关键字,认为它不是必需的,但是如果没有它们,我的程序将无法运行。我认为 extern 仅用于前向声明?为什么需要 const全局定义/初始化 ?它与它们在其中定义的名称空间有关吗?

解决方案


它意味着减少代码当包含多个文件中的常量时膨胀


我建议不要专注于这种优化,除非它变得非常必要,最简单的设计:直接在头文件中定义这些常量,并包含来自所有需要访问这些常量的翻译单元(.cpp文件)的头文件。由于这些对象是 const ,它们将会有内部链接,并且链接器不会因违反One Definition Rule而尖叫。


我尝试删除globals.cpp中的extern关键字,认为它不是必需的,但是我的程序不会在没有它们的情况下运行


这是因为具有静态存储持续时间的命名空间范围 const 对象(如 pi 变量)有内部链接,除非你明确地将它们定义为 extern


我以为extern只用于前向声明?

extern 用于声明在另一个翻译单元(.cpp文件)中定义的变量。如果对象是 const ,定义它的翻译单元需要明确地标记为 extern 以便它有外部链接,并且可以从其他翻译单元看到(如果对象不是 const ),则不需要这样做。


它与它们在其中定义的名称空间有关吗?


不,这是所有具有静态存储持续时间的命名空间级别 const 对象的规则,并在C ++标准的[basic.link] / 3中指定:


名称空间范围(3.3.6)的名称具有内部链接,如果它是

的名称

(3.1)[...] - 显式声明
声明为static的变量,函数或函数模板;或者

(3.2) - 非易失性常量限定类型的变量,既不明确声明为extern,也不声明为具有外部链接;或

<3.3> - 一个匿名工会的数据成员。



I'm running a simple program similar to what I found here. It's meant to reduce code bloat when including constants in multiple files. It does this by using const global variables within a namespace with their respective extern forward declarations.

globals.h

#ifndef GLOBALS_H_
#define GLOBALS_H_

namespace Constants
{
    // forward declarations only
    extern const double pi;
    extern const double avogadro;
    extern const double my_gravity;
}

#endif

globals.cpp

namespace Constants
{
    // actual global variables
    extern const double pi(3.14159);
    extern const double avogadro(6.0221413e23);
    extern const double my_gravity(9.2); // m/s^2 -- gravity is light on this planet
}

source.cpp

#include <iostream>
#include <limits>

#include "globals.h"

int main()
{
    double value_of_pi = Constants::pi;

    std::cout << value_of_pi;

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cin.get();

    return 0;
}

I assume that Constants::pi gets the value pi contained in the globals.cpp Constants namespace, and is able to do so because it has access to the namespace itself from the included globals.h. What I don't understand is why the const global definitions/initializations in globals.cpp need the extern keyword? I tried removing the extern keywords in globals.cpp thinking that it wasn't needed, but my program won't run without them. I thought extern was only used for forward declarations? Why are they needed for the const global definitions/initializations? Has it something to do with the namespace they are defined in?

解决方案

It's meant to reduce code bloat when including constants in multiple files

I would suggest not to focus on this kind of optimizations unless it becomes really necessary, and rather choose the simplest design: define those constants directly in the header file and include that header file from all translation units (".cpp files") that need to access those constants. Since those objects are const, they will have internal linkage and the linker won't be screaming at you due to violations of the One Definition Rule.

I tried removing the extern keywords in globals.cpp thinking that it wasn't needed, but my program won't run without them

That's because namespace-scope const objects with static storage duration (like your pi variable) have internal linkage unless you explicitly define them as extern.

I thought extern was only used for forward declarations?

extern is used to declare a variable that is defined in another translation unit (".cpp file"). If the object is const, the translation unit that defines it needs to explicitly mark it as extern in order for it to have external linkage and be visible from other translation units (this wouldn't be necessary if the object were not const).

Has it something to do with the namespace they are defined in?

No, this is the rule for all namespace-level const objects with static storage duration, and it is specified in paragraph [basic.link]/3 of the C++ Standard:

A name having namespace scope (3.3.6) has internal linkage if it is the name of

(3.1) [...] — a variable, function or function template that is explicitly declared static; or,

(3.2) — a variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external linkage; or

(3.3) — a data member of an anonymous union.

这篇关于extern如何在命名空间中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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