与使用实例变量相比,使用类模板参数有什么好处?
What's the benefit of using a class template parameter over using an instance variable?
当接触到微控制器编程(Arduino)时,我看到了以下类来控制特定引脚上的LED:
template <const uint8_t PIN>
class LED
{
public:
LED()
{
pinMode(PIN, OUTPUT);
}
void turnOn()
{
digitalWrite(PIN, HIGH);
}
void turnOff()
{
digitalWrite(PIN, LOW);
}
};
我可以通过
使用它LED<8> led;
led.turnOn();
点亮引脚8上的LED。
但我问自己:为什么引脚作为模板参数给出,为什么不作为实例属性?头等舱比这个有什么好处?
class LED
{
public:
LED(uint8_t ledPin) : pin(ledPin)
{
pinMode(pin, OUTPUT);
}
void turnOn()
{
digitalWrite(pin, HIGH);
}
void turnOff()
{
digitalWrite(pin, LOW);
}
private:
uint8_t pin;
};
,并像这样使用:
LED led(8);
led.turnOn();
使用第一个类是否比第二个类有优势,或者这只是一个品味问题?:)
"使用第一个类比第二个类有优势吗?还是这只是一个品味问题? ":)"
是的。在模板情况下,编译器可以直接使用数值,而不需要存储变量,节省内存(在非模板情况下,数字必须存储在RAM中)和功耗(您需要指令将字节保存到内存中,然后加载到寄存器中,而不是直接加载到寄存器中)。
这两个节省是如此之小,在普通PC的情况下,它真的不重要,但在小型设备(如微控制器)与低RAM(~小于1MB)和慢CPU的情况下,每一个字节的问题。
然而,如果你使用更多的引脚模板(不同的编号),你的应用程序将包含多个方法来打开和关闭它(对于每个使用的引脚编号)增加可执行文件的大小。在这种情况下,你是在为数据和CPU功耗节省内存,而不是为应用程序节省内存,然后这取决于你更需要什么——更小的应用程序有更大的内存和CPU功耗,或者反之亦然。
正如Laethnes所指出的,它可以帮助提高速度和内存消耗。我还想指出一些更基本的东西:
模板参数强制在编译时做出决定。
这是一个关于你的代码和它应该如何使用的非常有力的声明。就你的情况而言,我认为这是合适的。
您的示例处理具有LED附件的Arduino板。在任何类似的设置中,你都可以提前知道LED的哪个数字引脚会亮起。你如何设置你的硬件是不可能在程序运行时改变的。
将引脚作为模板参数是对基本假设的严格执行;它使得不可能运行时决定影响LED的引脚编号。如果它是一个普通的构造函数参数,你的类的用户可以在运行时做一些计算,然后根据这些计算的结果决定LED在上的哪个引脚,在你的情况下,这可能不是一个有效的事情。
当然,也许你真的需要处理运行时硬件配置的变化。如果是这种情况,模板参数只会成为您的障碍。一般来说,如果可以进行编译时强制执行,那么所做的对正确性是有利的。- 传递给std::function template的template参数究竟代表什么
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- C++部分概念 id:显式模板规范顺序/第一个参数的特殊状态的原因是什么?
- 引用捕获和在 lambda 中通过引用发送参数有什么区别 (C++)
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- 读取大文件(>2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么?
- 未命名的非类型模板参数有什么意义?
- 有什么方法可以将具有不同模板参数的模板类实例放入向量中?
- 什么是仅调用一次并调用参数的控制台应用
- 在模板参数中使用 {} 在 type_trait{} 中时,其作用是什么<T>?
- 在 C 和 C++ 中作为函数参数,int **a 和 int a[][] 之间有什么确切的区别
- 为什么或在什么情况下,你会将参数作为C++中的引用(或指针)传递给函数?
- 没有大小参数的CString::GetBuffer()做什么
- 可变参数模板和省略号有什么区别?
- 当通知迭代器参数初始化为空列表的开头时,list::insert 行为是什么?
- C++ [错误] 声明'char '隐藏参数。什么意思?
- 用相同的参数声明两个构造函数的最偶像化的方法是什么?
- 使用作为参数返回的指针的最佳做法是什么
- C++构造函数调用 boost::文件系统::p ath 作为参数 - 什么也没发生
- 如果我只想指定哈希函数,我应该传递给unordered_map的存储桶计数参数什么?