C++知识笔记

前言:最近在复习,参考了很多资料,随手把小知识点记录下来,没事儿看看。

C++ 和 C 区别

  • 设计思想上:C++是面向对象的语言,C是面向过程的结构化编程语言。
  • 语法上:C++具有封装、继承、多态三种特性;C++支持范式编程,如模板类、函数模板等;C++相比C增加了很多类型安全的功能,比如:强制类型转换。

i++ 和 ++i区别

  • ++i先自增1,再返回;i++先返回i,再自增1
  • 实现
int& int::operator++(){ // ++i 实现
    *this += 1;
    return *this;
}
const int int::operator(int){ // i++ 实现
    int oldValue = *this;
    ++(*this);
    return oldValue;
}

请写个函数在mian函数执行前先运行

  • 声明:仅仅是把变量的声明的位置及类型提供给编译器,并不分配内存空间;
  • 定义:要在定义的地方为其分配存储空间。定义也是一种声明。
  • 相同变量可以再多处声明,但有且仅有一个定义。
  • extern关键字:extern关键字声明变量名而不定义。
  • 如果声明时进行了初始化,就会被当做定义,即便是前面加了extern。只有当extern声明位于函数外部时才可以被初始化。
    extern double PI=3.14; // 尽管是extern这是定义。

“零值比较”?

  • bool类型:if(flag) ,bool:0为假false,非零为真true。
  • int类型:if(flag == 0)
  • 指针类型:if(NULL == flag) 但是在某些平台这种写法有时候会错,
    • 可写作 if(!flag) ,也表示空指针。
  • float类型:if((flag >= -0.000001) && (flag <= 0. 000001))

同一类不同对象之间赋值与复制

一. 对象之间的复制

  1. 其一般的两种形式为:
class Box
Box obj1 = obj2; //(注意此处与赋值的区别)
Box obj2(obj1)// 也行,调用复制构造函数
  1. 普通构造函数与复制构造函数的区别:
    (1)形式上:
Box(int h,int w,int len); //普通构造函数的声明,类名(形参表列)
Box(Box &b);  //复制构造函数的声明,类名(类名& 对象名)

(2)在建立对象时,实参类型不同。系统会根据实参的类型决定调用普通构造函数或复制构造函数。如:

Box box1(12,15,16); //实参为整数,调用普通构造函数
Box box2(box1); //实参是对象名,调用复制构造函数

二. 对象之间的相互赋值

  • 对象赋值的一般形式为:对象名1 = 对象名2;
  • 注意对象名1和对象名2必须属于同一个类。例如
Student stud1,stud2; // 定义两个同类的对象
stud2 = stud1; // 将stud1赋给stud2

特别说明:

  • 类的数据成员中不能包括动态分配的数据,否则在赋值时可能出现严重后果 ,答案如下:问题本质是,如果某个类的对象a里面有动态申请的数据,当你把a直接复制给同一个类的对象b的时候,a中的动态指针也给了b,这样a,b中的指针指向同一块内存。这样无论a或者b释放内存都会导致另外一个访内违例崩溃.
  • 解决这个问题需要自己重载赋值运算符和拷贝构造函数。如果不想重载,并且也不喜欢出现错误,那么就把这两类函数声明为私有。

同一类不同对象可以互相赋值吗?

  • 可以,但含有指针成员时需要注意。
  • 对比类的对象赋值时深拷贝和浅拷贝。

C++ *&符号含义和关系

#include<iostream>
using namespace std;
int main(){     
     int a = 123;  // a表示数字123,&a表示a在内存中的地址,也就是123在内存中的地址 
     cout<<"a: "<<a<<endl<<"a's address:"<<&a<<endl; // &a = 0019FF3C
     int *p = &a; // 此时p是一个指针,指向a所在的位置
     // p = 0019FF3C
     // 声明p之后,在p之前添加*,*p = 123 = p指向内存的值
     // 同时p也是 一个变量,在内存中也有一个地址储存它,但其地址不是a的地址
     // &p = 0019FF38 = p这个指针自己的内存地址
     // &p是一个内存地址,*&p表示&p指向地址内存空间的值,在这里表示a的地址0019FF3C
     //刚才我们已经知道*&p是a的地址,那么**&p就表示a的值123
return 0;}

【↑代码分析】
申明一个int变量a,赋值为123;
通过&运算可以知道 a的地址为:0019FF3C
申明一个int指针p,赋值为:0019FF3C, 也就是a的地址;
通过&运算可以知道p的地址为:0019FF38;
即在内存0019FF38储存的数据是0019FF3C;
如果仔细观察会发现p和a的地址是连续的,间隔为4,这与int是4个字节的数据类型的事实相符合。

strlen与sizeof的区别

  • strlen()是函数,在运行时才能计算。
    • 参数必须是字符型指针(char*),且必须是以’\0’结尾的。
    • 当数组名作为参数传入时,实际上数组已经退化为指针了。它的功能是返回字符串的长度。
    • 传递给strlen的是一个内存地址, 从那个地址往后面看, 到第一个值为0的地址的距离, 就是strlen的返回值.
  • sizeof()是运算符,而不是一个函数,在编译时就计算好了,用于计算数据空间的字节数。
    • sizeof 不能用来返回动态分配的内存空间的大小。
    • sizeof常用于返回类型和静态分配的对象、结构或数组所占的空间,返回值跟对象、结构、数组所存储的内容没有关系。如果sizeof的是一个数组, 则返回这个数组占据的空间大小。
    	int a[10];        sizeof(a); // = 40 = 4*10
    	char ch[]='abc';  sizeof(ch);// = 4 = 3+1 (3)
    
    • sizeof 不能求得void类型的长度,但能求void类型的指针的长度。sizeof(int*) == sizeof(void*) == sizeof(double*) == 4(Bytes)
    • 对一个指向数组的指针来说,sizeof他并不会返回数组的大小,只会返回这个指针的大小,往往是4个bytes. (根据编译和运行环境而定)
    • sizeof求得的结构体(及其对象)的大小并不等于各个数据成员对象的大小之和:
      • 只计算非静态成员
    • 传递给sizeof的一定是个变量,类型或者数组名,当sizeof的是一个变量或者类型, 则返回该变量和类型的大小。
    • 对于字符串string s; sizeof(string)sizeof(s)因编译器而不同,但计算的不是字符个数。sizeof("xxx")是字符个数+1。想知道字符串长度可以用s.size()或者s.length()
void test(string s) { // 传入s="abccccdd";
        int ss = (int)s.size();
        string s1 = "aa";
        int in = 2;
        // 结果:
        // int类型长度
        sizeof(int)4
        sizeof(in)4
        // string类型长度
        sizeof(s1)24
        sizeof(string)24
        sizeof(s)24
        // 不包含'\0',字符个数
        s.length()8
        s.size() 8
}
int main(){
    string s2 = "abccccdd";
    string s3 = "abcccaksfhasdkfhqpowiejfpoqjwfdpoqweifpoqwefhpoqewhfpoqewihfpoqihewflqihfpoqihfo ifjopqwheqwefqcdd";
     // 结果:
    sizeof(“abccccdd”)9 // 有'/0'
    sizeof("abcccaksfhasdkfhqpowiejfpoqjwfdpoqweifpoqwefhpoqewhfpoqewihfpoqihewflqihfpoqihfo ifjopqwheqwefqcdd"); // 99
    sizeof(s2)24 // string长度
    sizeof(s3)24
    s2.size()8 // 字符个数
    s3.size()98 
    test("abccccdd");
}

无符号数和有符号数比较

昨天师弟问个问题,以前没怎么注意过:
看下面代码了没~倒数第二行诶,j更大。为啥捏?因为.length() 获得的是unsigned类型,而 int j 是有符号数,在比较的时候会发生类型转换。负数存成补码,它转化成无符号数去比较的时候是非常大的数。所以会出现 j > p.length()

int main(){
    int j = -1;
    string p = "ab";
    string s = "a";
    cout<< j <<' '<<p.length()<<endl; //-1  2
    cout<<(j<(int)p.length())<<endl; // 1
    cout<<(j>p.length())<<endl; // 1
    cout<<(-1<2)<<endl; // 1
}

参考:牛客网技能树

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值