第一章:04从c语言到c++


代码运行环境

本节教程所有代码都是在win11系统,Qt 5.12.12版本,mingw编译工具环境编写运行。创建的工程类型为Qt Console Application。


1.内联函数

程序执行函数调用,系统要建立栈空间,保护现场,传递参数以及控制程序执行。有些时候函数功能本身很简单,代码很短,但使用频率很高,频繁切换会花费很多时间。为了减少函数调用切换的时间,一个解决方法就是不使用函数调用,直接将函数写入大方法中。这种方式的缺点就是每个需要调用的地方都要写,代码重复。因此引入内联思想,由编译器在编译过程中将函数写入。
内联函数的定义是在定义函数时使用修饰词 inline

//编译器优化了,会将简单函数直接优化为内联函数
//下面的代码无法在qt中测试内联函数与一般函数的执行区别
#include <QCoreApplication>
#include <iostream>
#include <ctime>
using namespace::std;
inline int max(int a, int b)  //在编译过程中,就会将这段代码添加进main函数
{
    return a >b ? a : b;
}
int testMax(int a, int b)
{
    int maxa = max(a,b);
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    clock_t start = clock();
    for(int i = 0; i< 10000; i ++)
    {
        int aa = testMax(5,8);    
    }
    clock_t finish = clock();
    double elapsedTime = double(finish - start) / CLOCKS_PER_SEC;
    cout << "Elapsed time: " << elapsedTime << " s\n";
    return a.exec();
}

1.1内联函数与带参数宏的区别

1.内联函数在编译时期在调用的地方展开,而宏是在预处理时期进行替换
2.内联函数在调用时期要求形参和实参类型要一致,有一个类型判断的过程,而且内联函数会先对实参表达式进行求值,然后传给形参。宏调用就是直接将实参与形参进行替换
3.c++建议简单函数使用inline(内联)

//编译器优化了,会将简单函数直接优化为内联函数
//下面的代码无法在qt中测试内联函数与一般函数的执行区别
#include <QCoreApplication>
#include <iostream>
#include <ctime>
#define MAX(a, b) (a) > (b) ? (a) : (b)     //宏定义,不需要参数类型
using namespace::std;
inline int max(int a, int b)  //内联函数
{
    return a >b ? a : b;
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    clock_t start = clock();
    for(int i = 0; i< 10000; i ++)
    {
        int aa = max(5,8);    
    }
    clock_t finish = clock();
    double elapsedTime = double(finish - start) / CLOCKS_PER_SEC;
    cout << "Elapsed time: " << elapsedTime << " s\n";
    return a.exec();
}

2.新的类型转换运算符

新式类型转换主要有这几种:const_cast(expr),static_cast(expr),reinterpret_cast(expr) dynamic_cast(expr),这个转换无法用旧式语句来进行转换
旧式转换:(T)expr, T(expr)

2.1 const_cast(expr)

const_cast(expr),这是用来移除对象的常量性(cast away the constness)
const_cast(expr)一般用于指针或者引用,移除常量性的目的不是修改它的内容,通常是为了让函数能够接受这个参数

#include <QCoreApplication>
#include <iostream>

using namespace::std;

//引入一个函数,让其能使用const类型的参数
void fun(int& var)
{
    cout << var << endl;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    const int var = 100;
    // int * p = &var;    这种写法是错误的,&var是 const int*,这无法转为 int*
    //使用const_cast<T>(expr)转换运算符
    int *p = const_cast<int*>(&var);     //这是正确写法,去除了const int* 的const属性
    *p = 200;        //这也是正确的,能修改
    cout << var << endl; //但是var = 100
    //查看 *p的地址与var的地址,发现两者其实是一个地址
    cout << p << endl;
    cout << &var << endl;
    int &pp = const_cast<int&>(var);  //  这是引用的用法
    pp = 500;
    cout << var<< endl;  //还是无法修改var的值

    //  fun(var);  这是错误的
    fun(const_cast<int&>(var));  //将const属性去掉,函数就能调用var这个变量,需要注意 输出的值为200,这是一个临时变量

    return a.exec();
}

2.2 static_cast(expr)

编译器隐式执行的任何类型转换都可用static_cast(expr)完成。当一个较大的算术类型赋值给较小的类型时,可以用static_cast进行强制转换。
可以将void*指针转为某一类型的指针
可以将基类指针转换为派生类指针
无法替代const_cast,不能将const转为非const类型

#include <QCoreApplication>
#include <iostream>

using namespace::std;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    short b = 10;
    int aa = b;    //隐式转换
    double pi = 3.14;
    short cc = pi;         //较大的算术类型赋值给较小的类型,这个写法没问题
    cout << cc << endl;
    short dd = static_cast<short>(pi);
    cout << dd << endl;

    //将void*指针转为某一类型的指针
    void*p = &aa;
    int* p2 = static_cast<int*>(p);
    cout << *p2 << endl;

    return a.exec();
}

2.3 reinterpret_cast(expr)

reinterpret_cast(expr)通常为操作上的位模式提供较低层的重新解释,也就是数据以二进制式重新解释。

#include <QCoreApplication>
#include <iostream>
#include <cstdint> // 需要包含这个头文件来使用 uintptr_t

using namespace::std;


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    int aa = 10;
    int* i = &aa;
    cout << *i << endl;
    char *p = "test a sample";
    uintptr_t ii;
    ii = reinterpret_cast<uintptr_t>(p);

    // int ii;
    // 下面的写法是错误的,会提示精度不够,因为int是4字节,指针是8字节
    //若系统是32位的则不会出错
    // ii = reinterpret_cast<int>(p);
    cout << ii <<" " << p<< endl;



    return a.exec();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值