C++宏将 .at() 替换为 []
C++ macro to replace .at() with []
我经常有一个索引越界错误,如果我使用.at()
而不是[]
来访问向量或字符串中的元素,很容易被捕获。但是,由于边界检查,at()
使我的程序减慢了 5 倍。
我正在尝试编写一个宏来替换.at(someVariable)
[someVariable]
这样我就可以取消注释宏,而不是手动用[]
替换每个.at()
。我已经阅读了有关 cppreference.com 宏的文档,但似乎无法设计出获得此功能的方法。
一般来说,我会避免使用这种宏,因为它们是"不可见的"(因此更改的语义对任何不知情的人都是巧妙地隐藏的),并且可以更改实际期望at
抛出界外的代码功能,即使在发布版本中也是如此。如果有的话,我会定义一些突出的东西,例如全大写AT
。
幸运的是,这实际上并不需要,因为"三大"C++运行时已经具有内置功能,可以有条件地启用operator[]
边界检查(这也具有比at
更具可读性的优点):
- 使用的是 g++/libstdc++,如果你通过
-D_GLIBCXX_DEBUG
你会得到 STL 容器的调试版本,它对operator[]
执行边界检查,以及对迭代器的许多其他调试检查; - CLang/libc++ 可以执行类似的检查,将
_LIBCPP_DEBUG
设置为 1; - 对于 Visual C++,类似的功能在
ITERATOR_DEBUG_LEVEL
设置为2
的情况下启用(默认情况下已在调试版本中启用)。
顺便说一下,其中一些错误(那些实际上溢出分配大小的错误,而不仅仅是向量的"逻辑有效"大小)也可以使用地址清理器(-fsanitize=address
在gcc和clang上)或valgrind(慢!)和类似的工具发现。
这里有一种不涉及宏的方法 - 它使用 c++17 的if constexpr
来简化:
#include <vector>
constexpr bool safe_mode = true; // or false
template<class Container>
auto at(Container& v, std::size_t i) -> decltype(auto)
{
if constexpr (safe_mode)
return v.at(i);
else
return v[i];
}
int& test(std::vector<int>& v)
{
return at(v, 6);
}
您可以使用数组取消引用运算符的全名:
#define at(x) operator[](x)
(x)
部分不是必需的,但只有在后面跟着参数时才替换at
,而不是单独替换单词。 您还需要在包含所有标准标头后定义它,否则它将替换具有它的类中的at
成员函数声明,从而导致编译错误。
相关文章:
- 使用宏将字符串解析为表达式C++
- 通过宏将函数参数传递给函数
- VC 链接器错误使用Dllimport/DLLEXPORT宏将标题包括在多个项目中
- 让宏将迭代参数传递到通过宏变量提供的代码体中
- Visual Studio 快速替换宏及其定义
- C++宏将 .at() 替换为 []
- 用其他东西替换宏内的goto
- 将"定义宏"替换为空实现
- 替换宏的文字
- 将宏替换为函数/模板
- 如何使用BOOST_LOG_TRIVIAL宏将任何内容记录到标准输出/标准和文件
- 程序使用TCHAR类型和TEXT宏将L附加到变量名
- 在 c++ 中替换宏中的括号
- 使用字符串替换函数将字符串的一部分替换为初始化的变量
- 寻找宏将取代功能
- Variadac宏将宏应用于所有参数
- C中的宏将0替换为1
- 用C++宏将文本替换为空
- 用静态常量变量替换宏是值得怀疑的
- c++ -如何消除宏?(将应用移植到c#中)