我问这个基本问题是为了让记录笔直.已经提到这个问题和它的目前公认的答案,这是不能令人信服的.然而,第二多投票的答案提供了更好的洞察力,但也不完美.
在阅读下面时,区分inline 关键字和"内联" 概念.
这是我的看法:
这样做是为了节省函数的调用开销.它更类似于宏式代码替换.没有什么可争议的.
inline关键字该
inline关键字是一个请求,以通常用于较小的函数的编译器,以便编译器可以优化它和做出更快的呼叫.编译器可以忽略它.
我对此提出异议,原因如下:
inline关键字.inline提及或不提及关键字,优化器都会自动内联较小的函数.很明显,用户对使用关键字的函数内联没有任何控制权inline.
inline有没有做内联的概念.把inline大/递归函数的未来将不利于小功能,不再需要它,为被内联.在只确定使用的
inline是保持一个定义规则.
即如果声明了一个函数,inline那么只有下面的东西是强制性的:
.cpp文件中包含该头),编译器也只生成1个定义并避免多个符号链接器错误.(注意:如果该函数的主体不同,那么它是未定义的行为.)inline功能的主体必须在使用它的所有翻译单元中可见/可访问.换句话说,在任何一个文件中声明inline函数.h和定义将导致其他文件的"未定义的符号链接器错误" .cpp.cpp"A"感觉完全错误,"B"感觉完全正确.
标准中有一些引用,但我期待一个答案,从逻辑上解释这个判决是真还是假.
编辑:我已经恢复了原始标题,但实际上我应该问的是:'C++链接器如何处理已在多个目标文件中定义的类方法'
假设我在这些行的标题中定义了一个C++类:
class Klass
{
int Obnoxiously_Large_Method()
{
//many thousands of lines of code here
}
}
Run Code Online (Sandbox Code Playgroud)
如果我编译一些在几个位置使用'Obnoxiously_Large_Method'的C++代码,生成的目标文件是否总是内联'Obnoxiously_Large_Method'的代码,或者它是否会针对大小进行优化(例如,当使用g ++ -Os时)并创建单个实例'Obnoxiously_Large_Method'并像普通函数一样使用它?如果是这样,链接器如何解决已实例化相同函数的其他目标文件之间的冲突?是否存在一些神秘的C++命名空间Juju,它使方法的单独对象实例不会相互冲突?
我想更好地了解编译器何时隐式实例化成员函数模板.
请考虑以下示例:
// example.h
struct Parent {
virtual void foo(double) {}
};
struct Child : Parent {
void foo(double d) { bar(d); }
template<typename T> void bar(T);
virtual void baz();
};
// example.cpp
#include "example.h"
template <typename T>
void Child::bar(T) {}
void Child::baz() {}
Run Code Online (Sandbox Code Playgroud)
通过编译[g++|clang++] -c example.cpp,GCC和clang都隐式实例化了函数模板Child::bar<double>.但是,以下看似微小的变化阻止了这一点:
foo不虚拟Child不继承Parentbazbaz不虚拟baz使用标题中的声明进行定义是否有关于何时进行隐式实例化的合理简洁解释,还是需要涉及标准的副本?我搜索了SO以寻找与隐式实例化有关的其他问题,但没有找到太多.我找到的最接近的是这个问题,但它是关于类模板中的虚函数(不是成员函数模板).
要明确:我理解通过在头文件中包含定义或显式实例化我需要的模板可以避免此问题.在挖掘为什么一个类(我无意中省略了它的明确实例)仍然愉快地编译和链接时,这仅仅是出于好奇点.
我有两个性能关键的功能,如下所示:
insertExpensive(Holder* holder, Element* element, int index){
//............ do some complex thing 1
holder->ensureRange(index);//a little expensive
//............ do some complex thing 2
}
insertCheap(Holder* holder, Element* element, int index){
//............ do some complex thing 1
//............ do some complex thing 2
}
Run Code Online (Sandbox Code Playgroud)
如何将2个功能组合在一起以提高可维护性?
解决方案1.
insertExpensive(Holder* holder, Element* element, int index){
do1();
holder->ensureRange(index);//a little expensive
do2();
}
insertCheap(Holder* holder, Element* element, int index){
do1();
do2();
}
Run Code Online (Sandbox Code Playgroud)
这将是丑陋的.如果do2想要一些局部变量,这也是不切实际的do1.
解决方案2.
insert(Holder* holder, Element* element, int index, bool check){ …Run Code Online (Sandbox Code Playgroud)