ami*_*min 3 c++ linker templates c++11
我已经问了一个类似的问题,但这个问题有点不同
我不想为每个简单的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;
}
Run Code Online (Sandbox Code Playgroud)
所以我使用模板来摆脱链接器投诉,并希望成员函数不会内联(是吗?):
// 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;
Run Code Online (Sandbox Code Playgroud)
然后我可以简单地在多个.cpp文件中使用日志类而不需要链接器投诉.
即使我使用这种方法会将成员函数变成内联吗?
通常,在头文件中进行每个实现都是一个坏主意,因为它可能导致较大项目的编译时间非常长.使用模板来避免这种情况也不是一个好主意,因为它不会改变这一事实.
inline只是对编译器的暗示; 它可能会忽略它并内联您的模板代码.简而言之:你的问题的答案无关紧要.标准/最佳方法是使用.cpp文件进行实现,即使您想避免它.
虽然将所有内容放在一个.h文件中通常是不好的做法,但有些情况下这样做会更方便.特别是在定义小类时,以及在原型设计阶段,代码可以快速改变很多.
我真的不建议使用模板来解决链接问题,因为它可能会减慢编译速度并导致混淆:就像创建一个函数接受参数时,除了该参数总是具有相同的值.无论如何,打字inline是短于template<typename T>)
因此,您必须在类主体中定义方法,或者inline在主体外定义时使用它们进行注释.这是等效的,因为C++会自动添加inline到类体中定义的方法.
您的担心似乎与生成的代码有关,您可能想知道二进制文件是否会增长太多.但是一切都很酷,因为无论inline注释如何,编译器都会查看每个函数调用并决定是内联还是生成调用.这意味着有时可以内联相同的函数(如果在循环中调用),有时也可以调用.
不同的编译器具有不同的启发式,但inline关键字对编译器的决策没有特别强烈的影响.你可以使用类似__forceinline或__attribute__((always_inline))更强烈的内容来内联函数,但即使这样,也不能保证所有对函数的调用都会被内联.相反,你可能__attribute__(noinline)对gcc感兴趣,它将(几乎)永远不会内联电话:
inline __attribute__(noinline) void log::log() // gcc
{
std::cout << ++m_cnt << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
如果您想真正了解代码中发生的情况,可以使用它-Winline来查看inline函数何时没有内联.
您还可以使用-Os或-Oz优化级别来更改内部编译器阈值,以便它可以减少内联.