在大多数情况下,缺少检查的最重要原因是性能。 C++ 遵循原则不要得到你不买的东西。如果您需要检查,请编写一个自定义类型来进行检查。您甚至可以让它仅在调试模式下进行检查。 (例如,std::vector 在其 operator[] 中实现。)如果你想要一种安全的语言,C++ 是你最糟糕的选择(在 C 和汇编之后)。 ;-) 但是您可以选择许多其他高级语言。
对于调试检查,标准库中有一个宏:assert():
#ifdef NDEBUG
#define assert(condition) ((void)0)
#else
#define assert(condition) /*implementation defined*/
#endif
因此,/*implementation defined*/ 部分检查condition。如果结果为false,那么通常会调用abort(),这又会立即中止进程(通常会生成一个可以在调试器中评估的核心转储)。
如果超出用于处理该值的数据类型,是否有任何方法可以使使用 Visual Studio 构建的程序停止工作(崩溃或发出警报等)?
与有符号/无符号数据类型相同,如果您使用无符号,但以某种方式加载“-1”值,无符号数据类型只是“接受”它,但会为您提供高于 0 的其他值。
是的,有一种方法——使用自定义类型作为原始类型的包装器。
一个简单的例子来证明这一点:
#include <cassert>
#include <iostream>
struct UChar {
unsigned char value;
UChar(unsigned char value = 0): value(value) { }
UChar(char value): value((assert(value >= 0), (unsigned char)value)) { }
UChar(int value): value((assert(value >= 0 && value < 256), value)) { }
UChar(unsigned value): value((assert(value < 256), value)) { }
UChar(long value): value((assert(value >= 0 && value < 256), value)) { }
UChar(unsigned long value): value((assert(value < 256), value)) { }
UChar(long long value): value((assert(value >= 0 && value < 256), value)) { }
UChar(unsigned long long value): value((assert(value < 256), value)) { }
UChar(const UChar&) = default;
UChar& operator=(const UChar&) = default;
~UChar() = default;
operator unsigned char() { return value; }
};
#define PRINT_AND_DO(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
// OK
PRINT_AND_DO(UChar c);
PRINT_AND_DO(std::cout << "c: " << (unsigned)c << '\n');
PRINT_AND_DO(c = 'A');
PRINT_AND_DO(std::cout << "c: " << c << '\n');
PRINT_AND_DO(UChar d = 'B');
PRINT_AND_DO(std::cout << "d: " << d << '\n');
PRINT_AND_DO(d = c);
PRINT_AND_DO(std::cout << "d: " << d << '\n');
// This will crash if NDEBUG not defined:
//PRINT_AND_DO(UChar e(3000));
//PRINT_AND_DO(c = 3000);
PRINT_AND_DO(d = -1);
}
输出:
a.out: main.cpp:9: UChar::UChar(int): Assertion `value >= 0 && value < 256' failed.
UChar c;
std::cout << "c: " << (unsigned)c << '\n';
c: 0
c = 'A';
std::cout << "c: " << c << '\n';
c: A
UChar d = 'B';
std::cout << "d: " << d << '\n';
d: B
d = c;
std::cout << "d: " << d << '\n';
d: A
d = -1;
bash: line 7: 31094 Aborted (core dumped) ./a.out
Live Demo on coliru
注意:
这只是一个演示 - 不是生产就绪代码。例如。不会捕获加法溢出或减法下溢,因为转换运算符 operator unsigned char() 会导致包装器实例在使用未在 struct UChar 中重载的运算符时转换回 unsigned char(但支持 unsigned char)。要解决此问题,必须为UChar 重载更多运算符。但是,我相信演示足以展示原理。