预处理系列之一(C++)

预处理阶段,要做的一件事就是对#define的处理

  1. 宏定义
    宏定义分两种,变量式宏定义和函数式宏定义,具体怎么使用我不想讲,主要讲一些注意点吧。
    1)变量型宏定义其实是没有类型的,它只是一个符号,在预处理阶段将符号替换;
    2)由于它不属于任何数据类型,所以不会被分配内存;
    3)进一步,在函数调用中,它不能作为参数传递,因为无论是传值还是传引用,参数都是有类型的,都占用内存。
    4)重复定义宏的时候,定义内容必须一模一样,如果想要重新定义,需要借助#undef,#undef的多次使用并不会报错。
    5)宏定义的实现并不是只有#define PI 3.14这一种方式实现,可以通过gcc -D选项定义一个宏,gcc -c -DPI=3.14 main.c;gcc -c -DMACHINE=68000 main.c;这种办法需要在MAKEFILE中配置。
  2. 条件预处理指令
    在源代码的配置管理当中通常有很多类似如下的几行代码:
    #if MACHINE == 68000
        int x;
    #elif MACHINE == 8086
        long x;
    #else    /* all others */
        #error UNKNOWN TARGET MACHINE
    #endif

    只是看代码不难知道什么意思,但应该尝试与实际场景联系起来。现在有两个平台,平台1要求MACHINE=68000时,全局变量x为整型,平台1要求MACHINE=8086时,全局变量x为长整型。
    更近一步地,我们可以更复杂
     

    #if MACHINE == 68000
        代码1
    #elif MACHINE == 8086
        代码2
    #else    /* all others */
        #error UNKNOWN TARGET MACHINE
    #endif

    这样平台1在MACHINE=68000时可以执行一串代码,平台2同理。

  3. 编译器还有自己定义的预处理指令,
    例如__FILE__的展开是当前源文件的绝对路径,是一个字符串。
    #include <stdio.h>
    using namespace std;
    
    int main(){
        printf("The file is:%s",__FILE__);
    }

    输出结果是:
    The file is:/Users/liujinyang/CLionProjects/leetcode/consumer_producer/main.cpp
    还有__LINE__的展开是当前代码所在行号,是一个整数。
     

    #include <stdio.h>
    using namespace std;
    
    int main(){
        printf("The file is:%s\n",__FILE__);
        printf("The line is:%d",__LINE__);
    }

    输出结果是:
    The file is:/Users/liujinyang/CLionProjects/leetcode/consumer_producer/main.cpp
    The line is:120
    这些都不是通过#define实现的,因为展开结果随着位置变化而变化,他们是编译器内建的特殊宏实现的。
    此外,C99还引入了一个特殊的标志符__func__,它是一个变量名,而不是宏定义,作用跟以上两个宏定义类似,用来显示所处函数的函数名。
     

    #include <stdio.h>
    using namespace std;
    void fuc1(){
        printf("%s\n",__func__);
    }
    
    void fuc2(){
        printf("%s\n",__func__);
    }
    int main(){
        printf("%s\n",__func__);
        fuc1();
        fuc2();
        return 0;
    }

    输出结果是:
    main
    fuc1
    fuc2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,根据提供的引用内容,没有找到关于C++实现Transformer的具体信息。但是,我可以为您提供一些关于Transformer的基本概念和C++实现的一般步骤。 Transformer是一种用于序列到序列(Sequence-to-Sequence)任务的模型架构,最初用于机器翻译任务。它由编码器(Encoder)和解码器(Decoder)组成,其中编码器将输入序列转换为一系列隐藏表示,解码器则使用这些隐藏表示生成输出序列。 要在C++中实现Transformer,您可以按照以下步骤进行操作: 1. 定义模型架构:在C++中,您需要定义Transformer的编码器和解码器的结构。编码器通常由多个自注意力层(Self-Attention Layer)和前馈神经网络层(Feed-Forward Neural Network Layer)组成,而解码器还包括一个注意力层(Attention Layer)。 2. 实现自注意力层:自注意力层是Transformer的核心组件之一。它通过计算输入序列中每个位置与其他位置的相关性来捕捉序列中的上下文信息。在C++中,您可以使用矩阵运算和线性代数操作来实现自注意力层。 3. 实现前馈神经网络层:前馈神经网络层用于对自注意力层的输出进行进一步的处理和映射。它通常由两个全连接层和激活函数组成。在C++中,您可以使用线性代数库或深度学习框架来实现前馈神经网络层。 4. 实现注意力层:注意力层用于解码器中,它根据编码器的隐藏表示和解码器的当前隐藏状态来计算上下文向量,以帮助生成输出序列。在C++中,您可以使用矩阵运算和线性代数操作来实现注意力层。 5. 训练和推理:实现模型的训练和推理过程,包括数据预处理、损失函数的定义、优化器的选择以及模型参数的更新和保存。 请注意,以上步骤仅为一般指导,具体的实现细节可能因您的具体需求和使用的库而有所不同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值