没有.cpp文件的c++类,没有内联函数

c++ classes without .cpp file without inline functions?

本文关键字:函数 cpp 文件 c++ 没有      更新时间:2023-10-16

我已经问过一个类似的问题,但这个有点不同

我不想为每个简单的c++类写一个。cpp文件。

当我在单个。hpp文件中编写类定义和声明时,链接器抱怨成员函数的多个定义没有在类体内实现或使用内联键盘定义。

例如,这将工作,但成员函数将成为内联:

// log.hpp file
#pragma once
#include<iostream>
class log {
  private:
    static int m_cnt = 0;
  public:
    void log();
};
inline void log::log() {
    std::cout << ++m_cnt << std::endl;
}

所以我使用模板来摆脱链接器的抱怨,并希望成员函数不会内联(是吗?):

// log.hpp file
#pragma once
#include<iostream>
template<typename T>
class log_t {
  private:
    static int m_cnt = 0;
  public:
    void log();
};
template<typename T>
void log_t<T>::log() {
    std::cout << ++m_cnt << std::endl;
}
// some random type (int)
typedef log_t<int> log;

然后我可以简单地在多个。cpp文件中使用日志类,而没有链接器的投诉。

当我使用这个方法时,成员函数会变成内联的吗?

虽然将所有内容放在单个.h文件中通常是不好的做法,但在某些情况下这样做更方便。特别是在定义小类时,以及在代码可以快速更改的原型阶段。

我真的不建议使用模板来解决链接问题,因为它会减慢编译速度并导致混乱:这就像创建一个接受参数的函数,而你却希望该参数总是具有相同的值。总之,输入inlinetemplate<typename T>短;)

所以你要么在类体中定义你的方法,要么用inline注释它们(如果在类体外定义的话)。这是等价的,因为c++会自动将inline添加到类体中定义的方法中。

您关心的似乎是生成的代码,您可能想知道二进制文件是否会增长太多。但是一切都很酷,因为无论inline注释如何,编译器都会查看每个函数调用并决定是内联还是生成调用。这意味着同一个函数有时可以内联(如果在循环中调用),有时可以被调用。

不同的编译器有不同的启发式,但是inline关键字对编译器的决定没有特别大的影响。您可以使用__forceinline__attribute__((always_inline))之类的东西使ask更强地内联函数,但即使这样也不能保证对函数的所有调用都将内联。相反,您可能对gcc的__attribute__(noinline)感兴趣,它(几乎)永远不会内联调用:

inline __attribute__(noinline) void log::log() // gcc
{
    std::cout << ++m_cnt << std::endl;
}

如果你真的想知道代码中发生了什么,你可以使用-Winline来查看inline函数何时没有内联。

您还可以使用-Os-Oz优化级别来更改内部编译器阈值,以便它将减少内联。

您可能感兴趣的相关问题:这里和这里

一般来说,将每个实现都放在头文件中是一个坏主意,因为它会导致大型项目的编译时间很长。使用模板来避免这种情况也不是一个好主意,因为它并没有改变这个事实。

inline只是对编译器的一个提示;它可能会忽略它并内联模板代码或不。简而言之:你的问题的答案并不重要。标准的/最好的方法是使用.cpp文件来实现,即使你想避免它。