Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c++;膨胀链接文件的常量符号 C++中的P>在头文件中是合法的,通常C方式是将外部声明放入头和定义中,只在一个编译单元中,但是在C++中,前者的技术导致增加的二进制,因为在链接时符号不被移除(用GNU LD和VisualStudio测试)。有没有一个好的方法来做这些事情?我只能想一个定义或C方式,但后者可能会给更少的优化空间_C++_Linker_Constants - Fatal编程技术网

c++;膨胀链接文件的常量符号 C++中的P>在头文件中是合法的,通常C方式是将外部声明放入头和定义中,只在一个编译单元中,但是在C++中,前者的技术导致增加的二进制,因为在链接时符号不被移除(用GNU LD和VisualStudio测试)。有没有一个好的方法来做这些事情?我只能想一个定义或C方式,但后者可能会给更少的优化空间

c++;膨胀链接文件的常量符号 C++中的P>在头文件中是合法的,通常C方式是将外部声明放入头和定义中,只在一个编译单元中,但是在C++中,前者的技术导致增加的二进制,因为在链接时符号不被移除(用GNU LD和VisualStudio测试)。有没有一个好的方法来做这些事情?我只能想一个定义或C方式,但后者可能会给更少的优化空间,c++,linker,constants,C++,Linker,Constants,你有两个真正的选择。可以使用外部链接定义常量,也可以不使用外部链接定义常量。使用内部链接时,假设启用了优化,则在每个实际使用常量的翻译单元中只需要一个副本 内部联系: // a.h const double AI_LIKE_COOKIES = 5.0; // a.h extern const double AI_LIKE_COOKIES; // a.c const double AI_LIKE_COOKIES = 5.0; 外部链接: // a.h const double AI_LIKE

你有两个真正的选择。可以使用外部链接定义常量,也可以不使用外部链接定义常量。使用内部链接时,假设启用了优化,则在每个实际使用常量的翻译单元中只需要一个副本

内部联系:

// a.h
const double AI_LIKE_COOKIES = 5.0;
// a.h
extern const double AI_LIKE_COOKIES;

// a.c
const double AI_LIKE_COOKIES = 5.0;
外部链接:

// a.h
const double AI_LIKE_COOKIES = 5.0;
// a.h
extern const double AI_LIKE_COOKIES;

// a.c
const double AI_LIKE_COOKIES = 5.0;
然而,您可能会问,“内联常量呢?”不幸的是,浮点操作数不能真正内联。无论何时在函数中使用浮点常量,该值都会作为常量存储在内存中。考虑这两个函数:

// In func1.c
double func1(double x) { return x + 5.7; }

// In func2.c
double func2(double x) { return x * 5.7; }
很可能,这两个文件都会在某个地方包含常量5.7,然后从内存中加载。没有真正执行优化*。您将获得两份5.7的副本,就好像您已经这样做了一样:

extern const double CONSTANT_1, CONSTANT_2;
const double CONSTANT_1 = 5.7;
const double CONSTANT_2 = 5.7;
double func1(double x) { return x + CONSTANT_1; }
double func2(double x) { return x * CONSTANT_2; }
*注意:在某些系统上,如果知道常量将链接到同一个二进制图像中,而不是从库中加载,则代码会变小

建议:在头文件中使用
extern
,并在一个翻译单元中定义常量。代码可能不会再慢,除非进行链接时间优化,否则这是确保最终产品中只有一个副本的唯一好方法

这听起来像是对八个字节的大惊小怪,不过

汇编程序:

这里有一个函数:

double func(double x)
{
    return x + 5.0;
}
这是x86_64上的汇编程序:

_Z4funcd:
.LFB0:
    .cfi_startproc
    .cfi_personality 0x3,__gxx_personality_v0
    addsd   .LC0(%rip), %xmm0
    ret
    .cfi_endproc
.LFE0:
    .size   _Z4funcd, .-_Z4funcd
    .section        .rodata.cst8,"aM",@progbits,8
    .align 8
.LC0:
    .long   0
    .long   1075052544

请注意符号
LC0
,它是一个包含值5.0的常量。内联只是使符号不可见,所以它不会显示在
nm
中。在每个使用常量的翻译单元中仍然会有一个常量的副本。

常量隐式放置在每个标题中会使其成为内部链接,因此它会在每个翻译单元中复制。我相信“C方式”是处理这个问题的正常方式


您还可以使用普通的内联函数定义“常量”(请参见
std::numeric\u limits::max()

这是逻辑行为。如果需要使模块依赖于外部名称,请改为包含
extern
。在大多数情况下,不需要。

对象声明为代码> const ,而未显式声明 ExtNe>代码>在C++中有内部链接。这意味着每个翻译单元都会得到它自己的对象副本

但是,由于它们具有内部链接,因此无法从其他翻译单元中命名,编译器可以检测对象本身是否未被使用——对于基本
const
对象,这仅意味着它的地址从未被使用;可以根据需要替换它的值,并从对象文件中省略它

即使在
-O1
,gcc也将执行此优化

$ g++ -O1 -c a.cc
$ g++ -O1 -c b.cc
$ g++ -o a a.o b.o 
$ nm a.o | c++filt | grep COOK
$ nm b.o | c++filt | grep COOK
$ nm a | c++filt | grep COOK
$ 

它仍然具有增加二进制大小的内部链接,但更糟糕的是,它现在是可修改的。static是const的默认值variables@AlanStokes哇,每天学习C和C++之间的不兼容的新东西。如果你使用最小的优化(<代码> -O1 < /代码>),const对象将在编译阶段消失。由于它们具有内部链接,编译器可以选择丢弃它们,因为它们不需要。@piotr:是的,大多数人也是这样。由于各种原因,“调试”配置对象文件将变得更大,未使用常量的额外副本不太可能是最大的因素。在调试配置中,您通常不需要关心二进制文件的大小。我不能将两者都标记为已回答,但我对您的答案投了更高的票。谢谢