C++学习笔记(二)

六.C++布尔类型(bool)

①bool类型在C++中是基本的数据类型,专门表示逻辑值,逻辑真用true表示,如果逻辑假false。
②bool类型在内存上占一个字节:数值1表示true,数值0表示false
③bool类型的变量可以接收任意类型表达式结果,结果非零则为true,为零则为false
eg.

#include <iostream>
using namespace std;
int main(void){
    bool b = false;
    cout << "size=" << sizeof(b) << endl;
    cout << "b=" << b << endl;
    b = 3 + 5;
    cout << "b=" << b << endl;//1
    b = 1.2 * 3.4;
    cout << "b=" << b << endl;//1
    char* p = NULL;//NULL-->(void*)0
    b = p;
    cout << "b=" << b << endl;//0
    return 0;
}

七.操作符别名(了解)

&& <==> and
|| <==> or
^  <==> xor
{  <==> <%
}  <==> %>
......

eg.

#include <iostream>
using namespace std;
int main(void)
<%
    int i = 0;
    int j = 1;
    if(i or j)<%
        cout << "true" << endl;
    %>
    else <%
        cout << "false" << endl;
    %>
    return 0;
%>

八.C++的函数

1.函数重载(overload)

①定义
在相同作用域,定义的同名函数,但是它们的参数必须有所区分,这样的函数将构成重载关系。
(注:函数能否重载和返回类型无关)
eg.

#include <iostream>
using namespace std;
void func(int i){
    cout << "func(int)" << endl;
}
void func(int a,int b){
    cout << "func(int,int)" << endl;
}
//double func(int i,int j){}//error
void func(int a,float b){
    cout << "func(int,float)" << endl;
}
int main(void){
    func(10);
    func(10,20);
    func(10,1.23f);
    //函数指针的类型决定匹配的重载版本
    void (*pfunc)(int,float) = func;
    pfunc(10,20);//func(int,float)
    return 0;
}

②函数重载匹配
调用重载关系的函数时,编译器会根据实参与形参的匹配程度,自动选择最优匹配版本,比如g++编译器匹配一般规则:
完全匹配>=常量转换>升级转换>降级转换>省略号匹配
eg.

#include <iostream>
using namespace std;
//char->int:升级转换
void bar(int i){
    cout << "bar(1)" << endl;
}
//char->const char:常量转换
void bar(const char c){
    cout << "bar(2)" << endl;
}
//short->char:降级转换
void fun(char c){
    cout << "fun(1)" << endl;
}
//short->int:升级转换
void fun(int i){
    cout << "fun(2)" << endl;
}
//省略号匹配
void hum(int i,...){
    cout << "hum(1)" << endl;
}
//double->int:降级转换
void hum(int i,int j){
    cout << "hum(2)" << endl;
}
int main(void){
    char c = 'a';
    bar(c);
    short  s = 10;
    fun(s);
    hum(10,1.23);
    return 0;
}

函数重载原理
C++编译器是通过对函数进行换名,将参数表的类型整合到新的函数名中,解决函数重载和名字冲突的矛盾。

笔试题:C++中 extern “C” 声明的作用?
可以在函数声明前面加入extern “C”,要求C++编译器不对该函数进行换名,便于C程序直接调用该函数.
(注:被 extern “C” 声明的函数无法重载)

2.哑元参数

①定义
定义函数时,只有类型而没有变量名形参成为哑元.

void func(int /*哑元*/){
	...
}

②使用哑元场景
–》在操作符重载,区分前后++、–
–》为了兼容以前的旧代码
eg.

算法库:void math_func(int a,int b){...}
使用者:
		int main(void){
			math_func(10,20);
			...
			math_func(30,40);
		}
-----------------------------------------------	
升级算法库:void math_func(int a,int/*哑元*/){...}
使用者:
		int main(void){
			math_func(10,20);
			...
			math_func(30,40);
		}

3.缺省参数(默认实参)

①定义
可以为函数的部分参数或全部参数指定缺省值,调用该函数时,如果不给实参,就取缺省值作为默认实参。

void func(int a,int b,int flag=0/*缺省参数*/){}

②靠右原则,如果函数的一个参数有缺省值,那么该参数右侧的所有参数都必须带有缺省值。
③如果函数的定义和声明分开,缺省参数应该是写在函数的声明部分,而定义部分不写。

void func(...);//函数声明
void func(...){...}//函数定义

eg.

#include <iostream>
using namespace std;
//函数声明
void func(int a,int b = 20,int c = 30);
//void func(int i){}//歧义错误
int main(void){
    func(11,22,33);//11 22 33
    func(11,22);//11 22 30
    func(11);//11 20 30
    return 0;
}
//函数定义
void func(int a,int b/*=20*/,int c/*=30*/){
    cout << "a=" << a << ",b=" << b << ",c=" 
        << c << endl;
}

4.内联函数(inline)

①定义
使用inline关键字修饰的函数即为内联函数,编译器将会尝试进行内联优化,可以避免函数调用的开销,提高代码执行效率。

inline void func(void){}//内联函数

(理解:正常程序运行时,调用函数这个过程会消耗时间;若使用内联函数,则把要调用的函数直接放到原有程序中,这样就减少了调用的时间,但相应的也就增加了内存。)

使用说明
–》多次调用的,小而简单的函数适合内联
–》调用次数极少或大而复杂的函数不适合内联
–》递归函数不能内联优化
–》虚函数不能内联优化

(注:内联函数只是一种建议而不是强制要求,能否进行内联优化是由编译器决定的,有些函数不加inline修饰也会默认处理为内联优化,而有些函数即便加了inline修饰也会被编译器忽略掉。)

九.C++动态内存管理

1.C语言动态内存管理

①分配:malloc()
②释放:free()

2.C++动态内存管理

①分配:new/new[]
②释放:delete/delete[]
eg.1

#include <iostream>
using namespace std;
int main(void){
    //int* pi = (int*)malloc(4); C语言
    int* pi = new int; //C++
    *pi = 123;
    cout << *pi << endl;
    //free(pi);//C语言
    delete pi;//C++
    pi = NULL;//防止野指针

    //动态分配内存同时初始化
    int* pi2 = new int(321);
    cout << *pi2 << endl;//321
    (*pi2)++;
    cout << *pi2 << endl;//322
    
    delete pi2;
    pi2 = NULL;
    return 0;
}

eg.2

#include <iostream>
using namespace std;
int main(void){
    //new内存保存多个数据(new数组)
    int* parr = new int[10];
    for(int i=0;i<10;i++){
        //*(parr+i) = i+1
        parr[i] = i+1;
        cout << parr[i] << ' ';
    }
    cout << endl;
    delete[] parr;
    parr = NULL;
    //new数组同时初始化,C++11标准支持
    int* parr2=new int[10]{9,8,7,6,5,4,3,2,1,0};
    for(int i=0;i<10;i++){
        cout << parr2[i] << ' ';
    }
    cout << endl;
    delete[] parr2;
    parr2 = NULL;
    return 0;
}

eg.3

#include <iostream>
using namespace std;
int main(void){
    //int* p1;
    //delete p1;//delete野指针危险
    
    int* p2 = NULL;
    delete p2;//delete空指针安全,但是没有意义

    int* p3 = new int;
    delete p3;
    //delete p3;//不能连续delete同一个指针

    return 0;
}

十.C++的引用(Reference)

1.定义

①引用即别名,就是某个变量的别名,对引用别名的操作与对变量本身完全相同.
(就相当于两个变量名指向了同一个内存地址,一个被修改,另一个也跟着修改。)
②语法规则

类型 & 引用名 = 变量名;  
eg.int& b = a;//b引用a,b就是a的别名
注:引用在定义时必须初始化,初始化以后绑定的目标不能再改变。
注:引用的类型与绑定的目标变量类型要相同。

eg.

#include <iostream>
using namespace std;
int main(void){
    int a = 10;
    int& b = a;//b引用a,b就是a的别名
    cout << "a=" << a << ",b=" << b << endl;
    cout << "&a=" << &a << ",&b=" << &b << endl;
    b++;//a++
    cout << "a=" << a << ",b=" << b << endl;

    //引用在定义时必须初始化
    //int& c;//error
    
    int d = 20;
    b = d;//ok,但不是修改引用目标,仅是赋值操作
    cout << "a=" << a << ",b=" << b << endl;
    cout << "&a=" << &a << ",&b=" << &b << endl;

    //引用类型和目标变量类型要一致
    char& r = d;//error

    return 0;
}

2.常引用

①定义引用时加const修饰,即为常引用,不能通过常引用修改引用的目标。
const 类型 & 引用名 = 变量名;
类型 const & 引用名 = 变量名;//和上面完全等价

eg:
int a = 10;   
const int& b = a;//b是a的常引用
b++;//error
a++;//ok,此时a和b的值都为11

②普通引用也可以叫做左值引用,只能引用左值;而常引用也可以叫做万能引用,既可以引用左值,也可以引用右值。
③关注左值和右值

左值(lvalue):可以放在赋值操作符左侧,可以被修改.
--》普通变量
--》前缀++--	
--》赋值表达式结果	 
右值(rvalue):只能放在赋值操作符右侧,不可以被修改,引用时要加const,常引用
--》字面值常量
--》类型转换结果的临时变量
--》加法(大多数、后++--)表达式结果的临时变量
--》函数中返回的临时变量

eg.

#include <iostream>
using namespace std;

int func(void) {
    int num = 100;
    cout << "&num=" << &num << endl;
    return num;
}

int main(void) {
    //int& r1 = 100;//error
    const int& r1 = 100;//ok
    cout << r1 << endl;

    char c = 'a';
    //首先要c转换为int类型,转换结果将保存到
    //临时变量,r2实际要引用是临时变量(右值)
    //int& r2 = (int)c;//error
    const int& r2 = (int)c;//ok,此时c相当于是常数了,所以引用的话要加const
    cout << "&r2=" << &r2 << endl;
    cout << "&c=" << (void*)&c << "\n" << endl;

    int a = 10;
    int b = 20;
    //加法表达式结果是临时变量(右值)
    //int& r3 = a+b; error
    const int& r3 = a + b;
    cout << r3 << endl;//30

    int& r4 = ++a;//ok
    cout << r4 << endl;//11
    cout << &a << ',' << &r4 << endl; //地址相同

    int& r5 = (a += b);
    cout << r5 << ',' << a << endl;
    cout << &r5 << ',' << &a << endl;

    //函数返回结果不是return的num,而是return时生成的临时变量(右值)
    //int& r6 = func();//error
    const int& r6 = func();//ok
    cout << "\n" ;
    cout << r6 << endl;//100
    cout << "&r6=" << &r6 << endl;

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

boss-dog

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

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

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

打赏作者

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

抵扣说明:

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

余额充值