C++ 可以在头文件中定义很长的类函数成员吗?
我在头文件中定义了一个类,并在同一个头文件中实现了它的功能。我并没有把inline关键字和函数定义放在一起,因为我认为编译器在默认情况下会将其视为一个内联函数——但inline只是对编译器的一个提示,对吗?如果编译器因为其长度而不将其视为内联函数,该怎么办?事实上,我从未收到“多个定义”的错误消息C++ 可以在头文件中定义很长的类函数成员吗?,c++,class,inline,C++,Class,Inline,我在头文件中定义了一个类,并在同一个头文件中实现了它的功能。我并没有把inline关键字和函数定义放在一起,因为我认为编译器在默认情况下会将其视为一个内联函数——但inline只是对编译器的一个提示,对吗?如果编译器因为其长度而不将其视为内联函数,该怎么办?事实上,我从未收到“多个定义”的错误消息 struct tmp { void print() { ...(very long) } }; EDIT@Leon(以下)表示我的答案(转载于以下)不正确。描述了正确
struct tmp {
void print() {
...(very long)
}
};
EDIT@Leon(以下)表示我的答案(转载于以下)不正确。描述了正确的答案——简而言之,如果编译器决定不内联函数,它仍然会将其放入对象模块中。但是链接器随后将在不同模块中选择一个(可能是多个)副本,并丢弃所有其他副本
您是对的:不会出现“多重定义”错误,因为每次编译器决定不将函数内联时,它都会使函数
在当前模块中保持静态。这意味着您的代码中可能会散落大量大函数的副本。EDIT@Leon(下面)说我的答案(下面复制)不正确。描述了正确的答案——简而言之,如果编译器决定不内联函数,它仍然会将其放入对象模块中。但是链接器随后将在不同模块中选择一个(可能是多个)副本,并丢弃所有其他副本
您是对的:不会出现“多重定义”错误,因为每次编译器决定不将函数内联时,它都会使函数在当前模块中保持静态。这意味着您的代码中可能会散落大量大型函数的副本
我并没有将内联关键字和函数定义放在一起,因为我认为编译器默认情况下会将其视为内联函数
是的,类主体中定义的成员函数是隐式内联的
。关键字不是必需的
内联只是编译器的一个提示,对吗?如果编译器因为其长度而不将其视为内联函数,该怎么办
是的,有点。实际上,inline
关键字有两种含义
第一个是您正在考虑的,它提示优化器将代码内联到调用站点的函数体中。正如您所说,这只是一个提示,如果优化器确定这样做会导致性能悲观(或者由于某些其他技术原因无法内联),那么它可以随意忽略此请求。内联关键字的这个含义可以说已经过时了。所有的优化编译器现在忽略内联关键字,因为他们的作者认为他们的启发式比程序员更聪明。这种情况几乎总是存在的,因此通过将函数标记为内联的方式来猜测优化器是毫无意义的
内联关键字的第二个含义是放宽一个定义规则(ODR),使得链接器可以看到同一函数的多个定义是合法的。(虽然链接器在这种情况下的行为是一个实现细节,但大多数链接器只是随意选择其中一个定义。当然,只有在它们都相同的情况下才能很好地工作。)内联关键字的这一含义仍然非常重要,并解释了为什么它今天仍然在代码中使用
这就是代码受益的意义。由于类主体中定义的成员函数被隐式标记为内联,因此不会从链接器中获得多个定义的符号错误
如果您在头文件中定义了函数,但不在类定义中,换句话说,如果您这样做了:
struct tmp {
void print();
};
void tmp::print()
{ ... }
然后,当头文件包含在两个或多个编译器(即翻译单元)中时,您将立即开始获取多重定义的符号错误。这是您需要在函数定义上添加inline
关键字的地方,不是因为您想让编译器“内联”它,而是因为您想免除自己的ODR
我并没有将内联关键字和函数定义放在一起,因为我认为编译器默认情况下会将其视为内联函数
是的,类主体中定义的成员函数是隐式内联的
。关键字不是必需的
内联只是编译器的一个提示,对吗?如果编译器因为其长度而不将其视为内联函数,该怎么办
是的,有点。实际上,inline
关键字有两种含义
第一个是您正在考虑的,它提示优化器将代码内联到调用站点的函数体中。正如您所说,这只是一个提示,如果优化器确定这样做会导致性能悲观(或者由于某些其他技术原因无法内联),那么它可以随意忽略此请求。内联关键字的这个含义可以说已经过时了。所有的优化编译器现在忽略内联关键字,因为他们的作者认为他们的启发式比程序员更聪明。这种情况几乎总是存在的,因此通过将函数标记为内联的方式来猜测优化器是毫无意义的
内联关键字的第二个含义是放宽一个定义规则(ODR),使得链接器可以看到同一函数的多个定义是合法的。(虽然链接器在这种情况下的行为是一个实现细节,但大多数链接器只是随意选择其中一个定义。当然,只有在它们都相同的情况下才能很好地工作。)内联关键字的这一含义仍然非常重要,并解释了为什么它今天仍然在代码中使用
这就是代码受益的意义。由于成员函数是在类a的主体中定义的