为何C++代码的隐式生成成员函数未出现在符号表中?
为什么C++中隐式生成或默认的成员函数不在符号表中?
先看你的示例代码:
#include <iostream> class Foo { public: Foo (int N) : values {new int[N]}{ for (int i = 0; i < N; i++) { values[i]=2*i; } }; private: int *values; }; int main() { Foo A {20}; Foo B {A}; Foo C {std::move(A)}; return 0; }
编译后执行nm -C a.out | grep Foo,输出只有:
00000000000011b8 W Foo::Foo(int) 00000000000011b8 W Foo::Foo(int) 000000000000122a W std::remove_reference<Foo&>::type&& std::move<Foo&>(Foo&)
哪怕给类加上Foo(const Foo&)=default;,nm输出还是没变化;但手动定义拷贝构造Foo(const Foo&){};后,就能看到对应的符号:
00000000000011ce W Foo::Foo(int) 0000000000001240 W Foo::Foo(Foo const&) 00000000000011ce W Foo::Foo(int) 0000000000001240 W Foo::Foo(Foo const&) 000000000000124f W std::remove_reference<Foo&>::type&& std::move<Foo&>(Foo&)
核心原因在于编译器的优化规则和特殊成员函数的生成逻辑:
- 按需生成+内联优化:C++标准规定,隐式生成的特殊成员函数(拷贝构造、移动构造、析构等)只有在被ODR-used(即需要具体定义的场景)时才会生成。但就算生成了,编译器会默认对这些简单的默认实现做内联优化——直接把函数逻辑嵌入调用处,不会生成独立的函数符号,自然在
nm里看不到。 =default和隐式生成等价:用=default声明的函数,本质还是编译器生成的默认实现,和隐式生成的规则完全一致,依然会被内联优化,不会留下独立符号。- 手动定义函数不会自动内联:当你手动编写函数体(哪怕是空实现),编译器不会自动内联该函数(除非显式加
inline关键字),因此会生成独立的函数符号,nm就能捕获到。
如果要验证这个结论,可以关闭内联优化后编译:
g++ -fno-inline your_code.cpp
再执行nm -C a.out | grep Foo,就能看到隐式生成或=default声明的拷贝构造、移动构造的符号了。
内容的提问来源于stack exchange,提问作者TCD
相关产品推荐
相关产品推荐

