C++内部类;"nm -C"输出中没有符号

4

我正在学习使用Linux上的gcc 4.8.1选项-frepo详细了解C++模板实例化。我的理解是,这个选项会对模板实例化进行一些清理操作,使得即使在多个翻译单元中隐式实例化相同的模板,每个实例也只会在链接的二进制文件中出现一次。如果需要特定的上下文,请参考以下示例文件:

// file: template.h
template <typename T>
class Box {
public:
    void func (const T & t) {}        // member function

    template <T t>
    T func_tmpl () { return t; }      // member function template

    template <T t>
    class inner {                     // inner class template
    public:
        const static T value = t;
    };
};

并且

// file: main.cpp
#include "template.h"

int main (int argc, char * argv[]) {
    Box<int> b;
    b.func(3);                        // member function invocation
    int x = b.func_tmpl<7>();         // member function temple instantiation
    Box<int>::inner<5> g;             // inner class template instantiation
    int y = g.value;
    return 0;
}

当我编译 (g++ -frepo -c main.cpp) 并检查符号 (nm -C main.o),我发现:

0000000000000000 T main
                 U Box<int>::func(int const&)
                 U int Box<int>::func_tmpl<7>()

正如您所预期的那样,funcfunc_tmpl被列为未定义的符号。我不确定的是为什么inner没有被列出来;它在类模板中定义,本身是一个类模板,并在main.cpp中实例化。有人能提供inner未包含在main.o符号中的原因吗?无论是否定义都可以。


nm 不显示类,它显示函数和全局变量。它将显示 Box<int>::inner<5>::value,但在这里它是“未使用的”。 - Marc Glisse
@MarcGlisse 谢谢您的快速回复。您评论的第一句话似乎合理并且可以解释事情。但是,我对第二句话很好奇:我该如何使它“被使用”?我已经尝试了几种方法,但似乎都没有效果。此外,Box<int>::inner<5>::value实际上是全局变量吗?我认为它的范围更为狭窄,因为需要使用::来标识它。再次感谢! - Eric Paniagua
1个回答

1
编译器发现Box<int>::inner<5>::value是一个常量,因此对象代码生成将其移除并用文字5替换名称。如果观察生成的汇编代码,你可能会看到类似于以下内容:
    movl    $3, -12(%rbp)
    leaq    -12(%rbp), %rdx
    leaq    -13(%rbp), %rax
    movq    %rdx, %rsi
    movq    %rax, %rdi
    call    _ZN3BoxIiE4funcERKi
    leaq    -13(%rbp), %rax
    movq    %rax, %rdi
    call    _ZN3BoxIiE9func_tmplILi7EEEiv
    movl    %eax, -4(%rbp)
    movl    $5, -8(%rbp)

这段代码对应于调用Box::func,然后将Box::func_tmpl的调用赋值给x,最后将y赋值为字面值5。请注意,将y赋值使用了字面值5
为了让符号出现在你的nm输出中,请使用成员本身,而不是其值。例如,存储它的引用:
    const int &y = g.value;

我很感激你详细的回答。我没有考虑到常量优化。多亏了你,下次我会特别留意这个。我试图给你的回答点赞,但显然我需要更高的声望才行。 - Eric Paniagua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接