简体   繁体   English

多个翻译单元中的内联函数

[英]Inline functions in multiple translation units

Let's start with the following set of C++ files: 让我们从以下C ++文件集开始:

// my_class.h
struct MyClass
{
  void my_func();
};

void MyClass::my_func()
{}


// f.h
void f1();
void f2();


// f1.cpp
#include "my_class.h"

void f1()
{
  MyClass a;
  a.my_func();
}


// f2.cpp
#include "my_class.h"

void f2()
{
  MyClass a;
  a.my_func();
}


// main.cpp
#include "f.h"

int main()
{
  f1();
  f2();

  return 0;
}

I tried to compile this code with 我试着用这个代码编译

$ g++ f1.cpp f2.cpp main.cpp

Obviously, the linker complained of duplicate symbol my_func : 显然,链接器抱怨重复的符号my_func

duplicate symbol __ZN7MyClass7my_funcEv in:
    /var/folders/yj/zz96q16j6vd1dq1_r3mz8hzh0000gn/T/f1-962ae7.o
    /var/folders/yj/zz96q16j6vd1dq1_r3mz8hzh0000gn/T/f2-aef78c.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

The next attempt I had was to move the function definition inside the class definition, so we get: 我的下一次尝试是在类定义中移动函数定义,因此我们得到:

struct MyClass
{
  void my_func()
  {}
};

Running the same g++ command, the program compiles successfully. 运行相同的g++命令,程序成功编译。 This is because functions defined in class definition are implicitly marked inline (§10.1.6 * 3). 这是因为类定义中定义的函数是inline隐式标记的(第10.1.6节* 3)。

The standard states: 标准规定:

A function declaration (11.3.5, 12.2.1, 14.3) with an inline specifier declares an inline function. 带有内联说明符的函数声明(11.3.5,12.2.1,14.3)声明了一个内联函数。 The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. 内联说明符向实现指示在调用点处函数体的内联替换优先于通常的函数调用机制。 An implementation is not required to perform this inline substitution at the point of call; 在呼叫点执行此内联替换不需要实现; however, even if this inline substitution is omitted, the other rules for inline functions specified in this section shall still be respected 但是,即使省略了这种内联替换,仍应遵守本节中规定的内联函数的其他规则

Which seems somewhat in contradiction to what is written on cppreference.com : 这似乎与cppreference.com上的内容相矛盾:

Because the meaning of the keyword inline for functions came to mean "multiple definitions are permitted" rather than "inlining is preferred", [...] 因为函数内联关键字的含义意味着“允许多个定义”而不是“内联是首选”,[...]

So as far as I understand, having a function defined in the class definition makes it implicitly inline which does not necessarily mean that the compiler will choose to inline its body but will a definition of it in every translation unit. 因此,据我所知,在类定义中定义的函数使其隐式inline ,这并不一定意味着编译器将选择内联其主体,而是在每个转换单元中定义它。 Is this correct? 它是否正确?

The second question comes regarding template classes. 关于模板类的第二个问题。 Separating the declaration/definition of a template class is a problem, as described here so we can only have function definitions in the class definition which makes it implicitly inline , again, right? 分离模板类的声明/定义是一个问题,如此处所述因此我们只能在类定义中使用函数定义,使其隐式inline ,再次,对吗? What is the impact of this? 这有什么影响?

Since we only have the choice of defining functions in class definitions when the class is a template, what is to be done about classes that are not template? 因为当类是模板时,我们只能选择在类定义中定义函数,所以对于不是模板的类,要做什么? Should we define function in source files and only keep the declaration in headers when possible? 我们应该在源文件中定义函数,只在可能的情况下将声明保留在头文件中吗?

So as far as I understand, having a function defined in the class definition makes it implicitly inline which does not necessarily mean that the compiler will choose to inline its body but will a definition of it in every translation unit. 因此,据我所知,在类定义中定义的函数使其隐式inline ,这并不一定意味着编译器将选择内联其主体,而是在每个转换单元中定义它。 Is this correct? 它是否正确?

Correct. 正确。 When defined inside the class it is marked as inline and it is okay that that defenition is brought into multiple translation units. 当在类中定义时,它被标记为内联,并且可以将该defenition带入多个翻译单元。 The compiler will handle that for you. 编译器将为您处理。

The second question comes regarding template classes. 关于模板类的第二个问题。 Separating the declaration/definition of a template class is a problem, as described here so we can only have function definitions in the class definition which makes it implicitly inline , again, right? 分离模板类的声明/定义是一个问题,如此处所述因此我们只能在类定义中使用函数定义,使其隐式inline ,再次,对吗? What is the impact of this? 这有什么影响?

This is not correct. 这是不正确的。 Templates are special. 模板很特别。 They aren't actually anything that will exist once the code is compiled. 它们实际上并不是编译代码后会存在的任何东西。 What a template is, is a recipe for stamping out a class or function. 什么是模板,是用于标记类或函数的方法。 As such, they are implicitly inline as well to allow the template to be included in every translation unit that uses it so the compiler can stamp out a concrete class/function from it as needed. 因此, 它们也隐式内联 ,允许模板包含在使用它的每个转换单元中,因此编译器可以根据需要从中删除具体的类/函数。 This means you can define class member functions outside of the class. 这意味着您可以在类之外定义类成员函数。

Since we only have the choice of defining functions in class definitions when the class is a template, what is to be done about classes that are not template? 因为当类是模板时,我们只能选择在类定义中定义函数,所以对于不是模板的类,要做什么? Should we define function in source files and only keep the declaration in headers when possible? 我们应该在源文件中定义函数,只在可能的情况下将声明保留在头文件中吗?

Typically you want to put your definitions in a cpp file. 通常,您希望将定义放在cpp文件中。 The benefit you get from this is you only need to recompile that one cpp file if you change the implementation of the functions. 您从中获得的好处是,如果更改了函数的实现,则只需要重新编译一个cpp文件。 If they were in the header file then you need to recompile every cpp file that includes that header file which leads to longer build times. 如果它们在头文件中,那么您需要重新编译包含该头文件的每个cpp文件,这会导致更长的构建时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM