是否保证只有一个非内联内联函数的副本?
Is there guaranteed to be only a single copy of a non-inlined inline function?
如果我声明了一个大的内联函数,而编译器选择将其作为一个独立的函数进行编译,是否保证程序中只有一个非内联内联函数的副本,或者编译器最终可能在不同的翻译单元中创建该函数的多个非内联副本?
或者,用一种几乎肯定会引起很多咬牙切齿的方式来重新表述:在预处理时间不是一个问题的情况下,在头文件中定义一个内联的大方法是能够重用该代码而无需在单独的翻译单元中编译/链接的有效方法吗?
您需要在这里非常具体,因为您要求保证。c++标准保证了程序的行为,而不是实现,即使这样也不是为了防止恶意编译器而编写的。许多实现细节都受到行为的有效约束。但也不完全是。
编译器可以自由地在可执行文件中嵌入任意函数的2^17个不同副本,无论是否内联。这是毫无意义的,但标准并没有禁止它!静态变量的值和地址必须是共享的,因为这是可观察的,并且如果c++代码可以访问每个函数的所有函数指针,它们必须比较相等(它们可以有不同的地址二进制表示,只需改变做==
的含义!)。
这会发生吗?没有,但你要我保证。c++标准给实现者留下了很大的空间。实现质量意味着现代编译器不会经常做一些愚蠢的事情。
在实践中,在每个使用它的.o
文件中创建一个内联函数。它被标记为特殊("弱")。当静态链接时,除了一个副本外,所有这些副本都将被丢弃。保留哪一个将取决于链接顺序,并且可以因构建而异(特别是部分构建)。以类似的方式只保留静态局部变量的一个副本。中指向函数或静态局部变量的所有指针必须在运行时比较相等。
动态链接会导致一些编译器在构建到dll时丢弃它。当.so
加载时,其他编译器会查看符号是否已经加载,如果已经加载,则不加载.so
中的副本。动态链接是函数的多个副本很可能继续存在并被访问的情况。如果没有发生这种情况,您就清楚了,如果发生了,请进行测试。c++标准没有描述动态链接
如果我声明了一个内联的大函数,而编译器选择将它作为一个独立的函数编译,那么在程序中是否保证只有一个非内联内联函数的副本,
。没有这样的保证。保证的是,在函数中声明的任何静态变量只有一个副本,并且如果您取函数的地址,您将始终得到相同的值。
或者编译器最终可能在不同的翻译单元中创建该函数的多个非内联副本?
。它们甚至可能不完全相同:如果它在一个翻译单元中看到参数总是null,它可以省略if (arg != nullptr
…'的代码。
我建议你仔细思考下面的问题:
"inline"关键词vs " inline "概念
为了优化,如果inline
函数为:
- 足够大,那么编译器可能不会做"内联"
- 足够短,那么编译器可能会做"内联"
然而,在这两种情况下,一个定义规则(ODR)是保证的,因为您使用了inline
关键字。
- 如何从构造函数副本 T(const T&)调用对象 T?
- 将 MatrixXd 的行传递给要修改的函数,而不在 Eigen 中创建副本
- 无法识别的类函数副本
- 当类型适当的构造函数可用时,为什么一个编译器尝试使用已删除的副本构造函数
- C ++引用函数参数似乎包含原始对象的副本,而不是充当"real reference"
- 为什么添加析构函数(甚至是空的)会破坏我的结构,该结构使用 ref 转发和折叠来保存 ref 或值的副本?
- 将(临时的?)std::string传递给使用它来构造一个接受副本的对象的函数的最佳方法是什么?
- 为什么没有为函数参数删除副本
- 为什么函数对实际参数的副本进行操作
- 我们如何在 C 中制作函数指针的深层副本
- 如何声明接受转发引用并返回引用或副本的函数模板
- 复制构造函数生成旧数组的错误副本
- MSVC 2017 在共享库中创建模板函数的副本
- 复制构造函数和运算符"="他们没有打印列表 l 的副本
- 是否有一种方法可以始终通过值(制作副本)而不是在使用类成员函数时通过参考来传递
- 如何为同一类对象的成员函数保留单独的变量副本?
- 给定一个填充无符号字符**的 C 函数,如何在没有中间副本的情况下用数据填充 std::vector
- 将动态数组作为副本传递给递归函数 C++
- C++中的构造函数副本、列表、指针和模板
- 在显式初始化期间尝试创建函数副本时出错