Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可以在头文件中定义很长的类函数成员吗?_C++_Class_Inline - Fatal编程技术网

C++ 可以在头文件中定义很长的类函数成员吗?

C++ 可以在头文件中定义很长的类函数成员吗?,c++,class,inline,C++,Class,Inline,我在头文件中定义了一个类,并在同一个头文件中实现了它的功能。我并没有把inline关键字和函数定义放在一起,因为我认为编译器在默认情况下会将其视为一个内联函数——但inline只是对编译器的一个提示,对吗?如果编译器因为其长度而不将其视为内联函数,该怎么办?事实上,我从未收到“多个定义”的错误消息 struct tmp { void print() { ...(very long) } }; EDIT@Leon(以下)表示我的答案(转载于以下)不正确。描述了正确

我在头文件中定义了一个类,并在同一个头文件中实现了它的功能。我并没有把inline关键字和函数定义放在一起,因为我认为编译器在默认情况下会将其视为一个内联函数——但inline只是对编译器的一个提示,对吗?如果编译器因为其长度而不将其视为内联函数,该怎么办?事实上,我从未收到“多个定义”的错误消息

struct tmp {
    void print() {
       ...(very long)
     }
};

EDIT@Leon(以下)表示我的答案(转载于以下)不正确。描述了正确的答案——简而言之,如果编译器决定不内联函数,它仍然会将其放入对象模块中。但是链接器随后将在不同模块中选择一个(可能是多个)副本,并丢弃所有其他副本



您是对的:不会出现“多重定义”错误,因为每次编译器决定不将函数内联时,它都会使函数
在当前模块中保持静态。这意味着您的代码中可能会散落大量大函数的副本。

EDIT@Leon(下面)说我的答案(下面复制)不正确。描述了正确的答案——简而言之,如果编译器决定不内联函数,它仍然会将其放入对象模块中。但是链接器随后将在不同模块中选择一个(可能是多个)副本,并丢弃所有其他副本


您是对的:不会出现“多重定义”错误,因为每次编译器决定不将函数内联时,它都会使函数
在当前模块中保持静态。这意味着您的代码中可能会散落大量大型函数的副本

我并没有将内联关键字和函数定义放在一起,因为我认为编译器默认情况下会将其视为内联函数

是的,类主体中定义的成员函数是隐式
内联的
。关键字不是必需的

内联只是编译器的一个提示,对吗?如果编译器因为其长度而不将其视为内联函数,该怎么办

是的,有点。实际上,
inline
关键字有两种含义

第一个是您正在考虑的,它提示优化器将代码内联到调用站点的函数体中。正如您所说,这只是一个提示,如果优化器确定这样做会导致性能悲观(或者由于某些其他技术原因无法内联),那么它可以随意忽略此请求。内联关键字的这个含义可以说已经过时了。所有的优化编译器现在忽略内联关键字,因为他们的作者认为他们的启发式比程序员更聪明。这种情况几乎总是存在的,因此通过将函数标记为内联的方式来猜测优化器是毫无意义的

内联关键字的第二个含义是放宽一个定义规则(ODR),使得链接器可以看到同一函数的多个定义是合法的。(虽然链接器在这种情况下的行为是一个实现细节,但大多数链接器只是随意选择其中一个定义。当然,只有在它们都相同的情况下才能很好地工作。)内联关键字的这一含义仍然非常重要,并解释了为什么它今天仍然在代码中使用

这就是代码受益的意义。由于类主体中定义的成员函数被隐式标记为内联,因此不会从链接器中获得多个定义的符号错误

如果您在头文件中定义了函数,但不在类定义中,换句话说,如果您这样做了:

struct tmp {
    void print();
};

void tmp::print()
{ ... }
然后,当头文件包含在两个或多个编译器(即翻译单元)中时,您将立即开始获取多重定义的符号错误。这是您需要在函数定义上添加
inline
关键字的地方,不是因为您想让编译器“内联”它,而是因为您想免除自己的ODR

我并没有将内联关键字和函数定义放在一起,因为我认为编译器默认情况下会将其视为内联函数

是的,类主体中定义的成员函数是隐式
内联的
。关键字不是必需的

内联只是编译器的一个提示,对吗?如果编译器因为其长度而不将其视为内联函数,该怎么办

是的,有点。实际上,
inline
关键字有两种含义

第一个是您正在考虑的,它提示优化器将代码内联到调用站点的函数体中。正如您所说,这只是一个提示,如果优化器确定这样做会导致性能悲观(或者由于某些其他技术原因无法内联),那么它可以随意忽略此请求。内联关键字的这个含义可以说已经过时了。所有的优化编译器现在忽略内联关键字,因为他们的作者认为他们的启发式比程序员更聪明。这种情况几乎总是存在的,因此通过将函数标记为内联的方式来猜测优化器是毫无意义的

内联关键字的第二个含义是放宽一个定义规则(ODR),使得链接器可以看到同一函数的多个定义是合法的。(虽然链接器在这种情况下的行为是一个实现细节,但大多数链接器只是随意选择其中一个定义。当然,只有在它们都相同的情况下才能很好地工作。)内联关键字的这一含义仍然非常重要,并解释了为什么它今天仍然在代码中使用

这就是代码受益的意义。由于成员函数是在类a的主体中定义的