C++回顾<一>:结构体-string字符串-&运算符-const -内联函数 inline-函数重载-&引用 -常引用-动态开辟空间new

1.结构体

1.C中struct结构体

  • 想存放函数,得使用函数指针
#include <stdio.h>
typedef void (*pfunc)(); // 函数指针
struct Stu{
    char* name;
    int age;
    pfunc action; 		// 函数指针
};
void write_code(){
    printf("正在努力的写代码\n");
}
int main(){
    struct Stu stu = {"zhangsan",18,write_code};
    stu.action();  //  正在努力的写代码
    return 0;
}

2.C++中的struct结构体

  • C++中的struct结构体在定义变量,再也不需要写冗余的struct关键字

  • C++中的struct结构体,默认是public访问权限

  • 函数不占用结构体类型空间

    #include <iostream>
    using namespace std;
    struct Stu
    {
        int age;
        void wirte_code(){
            cout << "正在写代码" << endl;
        }
    };
    int main()
    {
        Stu stu;
        stu.age = 18;
        stu.wirte_code(); // 正在写代码
        cout <<sizeof(stu)<<" , "<< stu.age << endl; // 4 , 18  	// 就int的4字节;函数不占用结构体类型空间
        return 0;
    }
    

2.string类型字符串

  • at()是有边界检查 ; 越界访问 报错
  • [ ]运算符函数是没有边界的。会越界访问 不报错
  • front() 首字符,back() 尾字符
  • empty()判断是否为空
  • +或者append() 拼接字符串
  • getline(cin,变量) 输入可以空格 输出一行
	string name = "baidu.com";
	//获取具体的位置的某个字符。
        cout << name.at(0) << endl; //at是有边界检查的  ; 越界访问 报错
        cout << name[9] << endl;// [ ]运算符函数是没有边界的。会越界访问 : 不报错
	//        		首  h                尾部   m
	cout << name.front() << "," << name.back() << endl; 
	if(!name.empty())
                cout << "字符串对象中有字符" << endl;

        string name2 = "www.";
        //拼接字符串。
        cout << name2 + name << endl;         // www.baidu.com
        cout << name2.append(name) << endl;   // www.baidu.com

        string tmp;
        getline(cin,tmp);   //  输入可以空格   输出一行
        cout << tmp;

3.&运算符

  • & 取地址运算符。
  • &数组首 地址升维为一个数组指针
  • &函数地址升维为此函数的函数指针类型的指针
        int a = 10;
        int* p = &a;    // 指针 -> a 的地址
	
        int arr[3] = {100,1,3};
        int (*pa)[3] = &arr;           		//  &arr是一个数组指针
        cout << **(pa) <<"," << *(*pa) <<endl;		  //  100  ,  100
        cout << *(*pa+2) << ","<< *(*(pa)+2) <<endl;   //3
	
        void show()
        {
            cout << " AAAA" << endl;
        }
        // 函数指针
        void (*pfunc)() = show;		// show是 (void*)类型
        void (*pfunc_a)() = &show;	// 如果加了& 之后    void (*)() 函数指针类型
        pfunc();				  //  AAAA
        pfunc_a();                    		//  AAAA

4.const

  • C语言中 在 声明结构体 里,用const修饰,会报错 **: 声明结构体,没有内存,const修饰变量或指针都有内存 **
  • 当const修饰的变量 或 指针,必须 赋初值。但指针的特性:1.指针可以不用赋初始值,语法也允许野指针的存在
#include <stdio.h>
struct Stu{
	const int age;  // const修饰变量,声明结构体,没有内存,会报错;  现在编译器自动优化,不报错
};
int main(){
	struct Stu stu = {18};	// 初始化
        printf("%d\n",stu.age);//18
        return 0;
}
  • 在C++中有一个 符号常量表 的概念。这个 符号常量表 是由 编译器 维护,当使用 const 修饰的内置类型的变量时,C++的编译器就会把这个变量中的值 存放在 符号常量表 (直接赋值,编译器 才会 把它放在 符号常量表)
  • 变量存放在 符号常量表 就无法 使用指针 强制类型转换修改
#include <iostream>
using namespace std;
int main()
{
#if 0
        int const a = 100;    // 如果是这种直接赋值,编译器 会 把它放在 符号常量表。
        int* p = (int*)&a;    //  强制类型转换 失败
        *p = 200;             	//  修改失败
        cout << "a = " << a << endl;  // a = 100

#else
        int b = 100;
         int const a = b;   	 //如果出现这种传递的操作,编译器也不会把它放在符号常量表。
        int* p = (int*)&a;  	// 强制类型转换 成功 去掉 const
        *p = 200;           	//  修改成功
        cout << "a = " << a << endl; // a = 200

#endif
        return 0;
}
  • 当const 修饰 普通变量(a\b) 时,变量为只读,不可修改的属性。

  • 当const修饰指针变量时,

    ​ 在*前 则修饰的是 指针类型,此指针 不可以改变 指向空间中的
    ​ 在*后 则修饰的是这个 指针变量本身。也就是 指向的地址 是不可以变的,

    ​ 所以 不可以 指向别外的一块空间,但 可以改变是指向空间的

        int a = 100;
        const int b = 1000;
        //b = 99;                // 报错;不能 用const给变量'b' 赋值…

        const int* pa= &a;      // <==>int const *pa= &a;
        //*pa = 99; 		//  错误;只读变量 不可赋值
        pa =&b; 		    //  cout<<*pa<<endl;   // 1000 ;成功改指向

        int* const pb = &a;
        *pb = 99;		// 成功 改指向 内存空间中的 值的。
        //pb = &b;		 // 错误,不能改指向

5.C++内联函数 inline

  • 内联函数不能 逻辑过于复杂 或有 延时等待 或耗时操作,编译器将会自动停止内联。
  • C++内联函数是有代价的:函数代码的膨胀
#define ADD(x,y) (x+y)				// 在 预处理 阶段展开
#define MAX(x,y) (((x) > (y))? (x) :(y))
// 内联函数
inline int max(int a, int b)
{
        return a > b? a : b;
}
int main()
{
        int a = 10;
        int b = 20;
        int sum = ADD(a,b) * 5;	// 若#define ADD(x,y) x+y 则 sum =x + y * 5
        cout << sum << endl;    // 150
        cout << "-------------------------------------------------------" << endl;
        int c = 10;
        int d = 20;
        int e = MAX(c,++d);     //10 >++20? 10:++21  y=22
        cout << e << endl;      // 22
        cout << "-------------------------------------------------------" << endl;
        d = 20;
        int e1 = max(c,++d);    // 10 >21 ? 10 : 21
        cout << e1 << endl;     // 21
        return 0;
}

6.函数重载

  • 当同一作用域下的同名函数,如果出现,函数参数类型个数不同时,就会发生函数重载

  • 返回值 没关系;( 函数形参列表类型个数不同 )

    C++编译器,在编译时,根据函数中的参数类型与个数不同,在 符号表 中重新生成一个 新的函数名。所以同一作用域下的两个函数不会产生命名冲突。

    	int add(int a , int b) 	{	return a + b;	}
    	float add(float a, float b)	{	return a + b;	}
    

7.&引用

  • 类型& 变量名 = 另一个变量名;
  • 引用的本质:就是一个const修饰的指针,它指向一块已经 存在的固定的内存空间,所以 引用不会 出现野指针的情况
  • int* const p = &a; p 不可以 指向别外的一块空间,但 可以改变是指向空间的
            int a = 100;
            int* p = &a;        	// &取地址
            *p = 888;
            cout << a << endl;  //a=888

            int* const p = &a;	// 本质 
            //&引用
            int& b = a;        //引用,理解为变量的别名
            cout << b << endl;  //b=888
            b=999;
            cout << b <<","<< a << endl;  //b=999,a=999
            a=1111111;
            cout << b << endl;  //a=b=1111111
  • 函数传参,优先使用引用。因为他与指针一样高效,并保证了指向空间的合法性。是一种安全机制。
    void swap(int& a, int& b)	// 引用传参
    {
            int tmp = a;
            a = b;
            b = tmp;
    }
    int main()
    {
            int a  = 10, b = 20;
            swap(a,b);			// a=20,b=10
            return 0;
    }

8.常引用const &

  • const 类型& 变量名 = 常量 。const int& b = 10;
    void show(const string& str)	//常引用
    {
            cout << str << endl;
    }
    int main()
    {
            const int& b = 10;    // 加了 const 修饰的引用 就是一个 常引用,可以引用常量。
            //string& name1 = "www.baidu.com";   	//错误;要 指向一块 已经存在 的固定的内存空间
        
            const string& name1 = "www.baidu.com";  //正确  ; 
            //会临时开辟 一块内存空间; string tep = "wwww.baidu.com";   const string& name2 = tep;

            show("www.baidu.com");   // www.baidu.com
            return 0;
    }

字符串常量(“www.baidu.com”)是一个字符数组,它在程序编译时被分配在静态存储区域中,并且其内部元素是不可修改的。

一个非 const 引用不能绑定到一个临时对象字符串常量。当你尝试通过非 const 引用来初始化一个字符串对象时,编译器会报错。
因为引用是一个别名,通过它可以改变所引用的对象,而字符串常量是一个常量值,其值不能被修改。
所以,正确的方式应该是使用 const 引用来绑定到字符串字面值常量上,如下所示:

const string& name1 = "www.baidu.com";

这样做是允许的,因为使用 const 修饰引用表示所指向的对象是只读的,不能被修改,从而避免了引起系统运行错误的可能性

9.动态开辟空间new

  • new连续开辟的堆区空间,则需要使用delete[] 来释放
1.        int* p = new int(0);  
		delete p;//释放空间
2.       string* s = new string;
		delete s;
3.        double* d = new double;
		delete d;

4.        int* pa = new int[3]{0,1,2};    //在堆区 使用new连续开辟空间 并 初始化 。      C++11方式。
		delete [ ] pa;//释放连续空间
5.        int* pb = new int[3];           	//在堆区 使用new开辟了一块连续空间。
		delete [ ] pb;

定位new的使用方法

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值