C++ 11 enum和 assert

26 篇文章 0 订阅

C++(4)

enum

c->c++

C 语言中的 enum 对象,是可以被其它非枚举值,赋值,而 C++中的枚举变量,
则只能用枚举值来赋值。

c中:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
enum Season
{
    Spring, Summer, Autumn, Winter
};
int main()
{
    Season s;
    s = Spring;
    //s = 100; //c++不支持这种赋值
    return 0;
}

c+±>c++11

枚举体的声明和定义使用 enum class 或是 enum struct, 二者是等价的。
使用 enum class\enum struct 不会与现存的 enum 关键词冲突。
而且 enum class\enum struct 具有更好的类型安全和类似封装的特性(scoped nature)。

#include <iostream>
using namespace std;

enum class Color1 {
    RED,
    GREEN,
    BLUE
};

enum struct Color2 {
    RED,
    GREEN,
    BLUE
};

int main()
{
    Color1 c1 = Color1::RED;
    Color2 c2 = Color2::RED;
    cout << (int)c1 << endl; // 输出0
    cout << static_cast<int>(c1) << endl; // 输出0
    cout << static_cast<int>(c2) << endl; // 输出0
    //cout << Color1::GREEN << endl; //未重载<<不能输出
    cout << (int)Color1::GREEN << endl; // 输出1
    cout << static_cast<int>(Color1::GREEN) << endl; // 输出1
    return 0;
}

指定类型

默认的底层数据类型是 int,
用户可以通过:type(冒号+类型)来指定任何整形(除了 wchar_t)作为底层数据类型。


#include <iostream>
using namespace std;

enum class color:int{ red, green, yellow};

enum class colorX:char { red, green, yellow };

int main()
{
    //使用域运算符访问枚举体成员,强转后打印
    std::cout << static_cast<int>(color::yellow) << std::endl; // 输出2
    std::cout << static_cast<int>(colorX::yellow) << std::endl; // 输出2
    
    cout << sizeof(color::red) << endl; // 输出4
    cout << sizeof(colorX::red) << endl;// 输出1
    return 0;
}

assert/static_assert

assert

assert 是一个宏,用于在程序中进行运行期断言(runtime assertion)。

它定义在 <assert.h> 头文件中。

断言用于验证程序中的某些条件是否为真。

如果断言的条件为假(即表达式的结果为 0),则程序会终止,
并输出一条错误消息,包括断言失败的位置(文件名和行号)。

assert 是运行期断言,
它用来发现运行期间的错误,不能提前到编译期发现错误,
也不具有强制性,也谈不上改善编译信息的可读性,既然是运行期检查,对性能当然是
有影响的,所以经常在发行版本中,assert 都会被关掉。

assert 的关键在于判断 expression 的逻辑真假,如果为 false,就会在 stderr 上
面打印一条包含"表达式,文件名,行号"的错误信息,然后调用 abort 结束整个程序。

//todo assert
#include <iostream>
#include <assert.h>
using namespace std;

// 自定义的字符串拷贝函数
char * myStrcpy(char * dst, const char * src) {
    // 运行期断言,确保 dst 和 src 不是 NULL
    assert(dst);
    assert(src);

    // 保存目标字符串的起始地址
    char * p = dst;

    // 使用指针遍历源字符串,并将每个字符复制到目标字符串中
    // 直到遇到源字符串的结束符 '\0'
    while ((*dst++ = *src++));

    // 返回目标字符串的起始地址
    return p;
}

int main() {
    // 定义两个字符数组,分别初始化为 "hello" 和 "world"
    char str1[10] = "hello";
    char str2[10] = "world";

    // 调用自定义的字符串拷贝函数,将 str2 的内容复制到 str1
    char * p = myStrcpy(str1, str2);

    // 输出复制后的 str1 内容
    cout << p << endl; // 输出 "world"

    // 定义两个空指针
    char *str3 = NULL;
    char *str4 = NULL;

    // 调用自定义的字符串拷贝函数,由于 str3 和 str4 是 NULL,会触发断言失败
    char * q = myStrcpy(str3, str4);

    // 这行代码不会被执行,因为上面的断言失败会导致程序终止
    cout << p << endl; // 输出 "world"

    return 0;
}

static_assert

static_assert 这个关键字,用来做编译期间的断言,因此叫做静态断言。

其语法很简单:static_assert(常量表达式,提示字符串)。

如果第一个参数常量表达式的值为真(true 或者非零值),那么 static_assert 不做
任何事情,就像它不存在一样,
否则会产生一条编译错误,
错误位置就是该 static_assert 语句所在行,错误提示就是第二个参数提示字符串。

使用 static_assert,我们可以在编译期间发现更多的错误,用编译器来强制保证
一些契约,并帮助我们改善编译信息的可读性,尤其是用于模板的时候。

static_assert 可以用在全局作用域中,命名空间中,类作用域中,函数作用域中,几乎可以不受限制的使用。

编译器在遇到一个 static_assert 语句时,通常立刻将其第一个参数作为常量表达
式进行演算,但如果该常量表达式依赖于某些模板参数,则延迟到模板实例化时再进行
演算,这就让检查模板参数成为了可能。


// 引入标准输入输出流库
#include <iostream>
// 使用标准命名空间
using namespace std;

// 静态断言,确保编译仅在 32 位的平台上进行
// 如果指针大小不是 4 字节(即 32 位),则编译失败
static_assert(sizeof(void *) != 4, "64-bit code generation is not supported.");
/*
该 static_assert 用来确保编译仅在 32 位的平台上进行,
不支持 64 位的平台,该语句可以放在文件的开头处,
这样可以尽早检查,以节省失败情况下的编译时间。
*/

// 模板函数 my_bit_copy,用于检查两个参数的宽度是否相同
template<typename T, typename U>
int my_bit_copy(T& a, U& b)
{
    // 静态断言,确保两个参数的宽度相同
    static_assert(
            sizeof(a) == sizeof(b),
            "参数必须具有相同的宽度"
    );
    // 由于静态断言的存在,如果参数宽度不同,编译将失败
    // 这里没有实际的代码实现,因为重点在于类型宽度的检查
    return 0; // 返回 0 表示函数执行成功
}

// 主函数
int main(int argc, char *argv[])
{
    // 定义一个整型变量 a 和一个浮点型变量 b
    int a;
    float b;
    // 调用 my_bit_copy 函数,由于 a 和 b 的宽度不同,编译将失败
    my_bit_copy(a, b);

    // 定义一个字符型变量 c
    char c;
    // 调用 my_bit_copy 函数,由于 a 和 c 的宽度不同,编译将失败
    my_bit_copy(a, c);

    // 返回 0 表示程序正常结束
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可能只会写BUG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值