• 【c++基础】第一章 C到C++过度阶段


    第一个C++程序:

    //输入输出流,c++标准头里没有.h
    #include 
    //标准名字空间,避免同名多人协作开发标识符冲突的问题
    using namespace std;
    
    int main(int argc, char const *argv[])
    {
    	int i;
        cout << "Hello world!!!" << endl; //输出
        cin >> i;//输入
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    编译:

    g++ hello.c //g++是gcc的提升,g++可以编译的,gcc有的不可

    使用namespace+名字

    namespace A{
    	int a=50;
    	void showInfo(){
    		cout <<"我在A中"<< endl;
    	}
    	//名字空间也可以互相嵌套
    	namespace B{
    		int a=200;
    		void showInfo(){
    			cout <<"我在A中的B中"<< endl;
    		}
    	}
    }
    namespace B{
    	int a=100;
    	void showInfo(){
    		cout <<"我在B中"<< endl;
    	}
    }
    
    int main(){
    	//使用::域名信息符,访问指定空间的变量和函数
    	//使用方式:名字空间::变量/函数
    	cout << A::a << endl;
    	cout << B::a << endl;
        cout << A::B::a << endl;
        A::showInfo();
        B::showInfo();
        A::B::showInfo();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    名字空间,相当于对全局作用域进行分隔。

    using关键字

    1. using+具体某个域中的标识:指定具体导入 如:using std::cout; using std::endl;
    2. using+namespace+名字空间:指定某个空间全部导入 如:using namespace std;
    3. 起别名 , 相当于typedef 的作用 如:using uint32=int;

    bool类型

    只有两个值(1true、0false)

    #include 
    
    using namespace std;
    
    int main()
    {
        bool ok;
        ok = true;
        cout << ok <
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    string字符串

    std::string

    边界检查:str.at(110);//解决越界问题

    #include 
    
    using namespace std;
    using std::string;
    
    int main()
    {
        string str="yao";
    
    //    cout << str[100] << endl;//越界,不提示
    //    cout << str.at(100) << endl;//越界,提示错误
        const char *c_str =str.c_str();//使用c指针访问字符串
        cout << c_str << endl;//yao
        
        cout << str.front() << endl;//字符串第一位API 即:y
        cout << str.back() << endl;//字符串最后一位API 即:o
        cout << str.length() << endl;//字符串的长度API 即:3
        cout << str.size() << endl;//字符串的大小API(不同于c字符串,没有'\0') 即:3
        
        string str1="liang";
        cout << str+str1 << endl;//追加字符串
        str+=str1;
        cout << str << endl;//yaoliang
        str.append(str1);//API追加字符串
        cout << str << endl;//yaoliangliang
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    结构体struct

    1. 可以定义函数,直接复制,不像c中声明
    2. 具有封装性,默认public,也可设置成private(私有的)
    3. class是struct衍生而来,默认是private
    #include 
    
    using namespace std;
    
    struct stu{
    public:
        string name="yaoliang";
        static int salary;
        int age;
        void write_code()
        {
            cout << "writing" << endl;
        }
    };
    
    //结构体大小
    //1.与非代码段和非静态区相关,函数在代码段(所以不计算),static修饰的变量在静态区(所以不计算)
    //2.string 的大小为32,在64位系统,以8字节对齐
    
    int main()
    {
        stu s;
        s.age=18;
        cout << s.age << endl;//18
        cout << s.name << endl;//yaoliang
        s.write_code();//write.ing
        cout << sizeof(stu) << endl;//40   (字符串32位+int(8字节对齐))
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    结构体成员函数指针的获取方式

    &的扩展

    #include 
    
    using namespace std;
    struct Stu{
        string name;
        int age;
        void show_stuInfo(){
            cout << "姓名:" << name << ",年龄:" << age << endl;
        }
    };
    
    void show_Info(){
        cout << "加油!!!" << endl;
    }
    
    int main()
    {
        int a=10;
        int *p=&a;
        cout << *p << endl;
        int arr[3]={1,2,3};
        int (*parr)[3]=&arr;
        cout << **parr <
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    在c++中的作用域:全局作用域,局部作用域(包括语句块作用域),类域,名字空间作用域

    const关键字:

    int a=100;
    printf("%d\n",*p);
    const int *p=&a;//指针可变,a值不能变
    int const *p=&a;//指针可变,a值不能变
    int * const p=&a;//指针不可变,a值可以改变
    const int * const p=&a;//都不可改变
    总结:const修饰指针,看*,*前+const,数值不变,*后+const,指针指向不变
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    #include 
    
    using namespace std;
    
    //所以在c++中,用下面这个
    const int my_max = 1024;
    //(在编译阶段替换,优于#define MAX 1024(在预处理阶段,不安全,error不好找))
    
    int main()
    {
        const int a=10;
        int *p=(int *)&a;
        *p=500;
        cout << " a = " << a << endl;//10
        cout << " *p = " << *p << endl;//500
        //原因:编译优化:const修饰的变量承接的是一个常量值,
        //编译器在编译阶段,将自动把a当作一个常量
        
        const int volatile b=20;//volatile 防止编译优化,可以随时改变
        int *q=(int *)&b;
        *q=200;
        cout << " b = " << b << endl;
        cout << " *q = " << *q << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    内联函数

    条件:不能耗时,不能循环,不能递归,代码精简(3不1精)

    功能:解决C中宏函数的问题。

    宏函数的优势:没有函数调用的过程,没有函数栈帧的开辟,没有函数的跳转

    内联函数的作用:大大提高了程序的运行效率,但是也有代价的,最终可执行代码膨胀

    #include 
    
    using namespace std;
    #define min_i(x,y)    ((x)<=(y)?(x):(y))
    #define min_t(type,x,y) ({type _x = x;type _y = y;_x<_y?_x:_y;})
    #define min(x,y)    ({\
                          const typeof(x)  _x = (x);\
                          const typeof(y) _y = (y);\
                          _x<_y?_x:_y;\
                         })
    //内联函数
    inline int my_min(int x,int y){
        return x

define和inline的区别:

  1. 内联函数在编译时展开,define在预处理阶段展开
  2. 内联函数直接嵌入到目标代码中,宏只做一个简单的文本替换
  3. 内联函数在编译阶段有类型检测,语法处理等功能,而宏没有
  4. inline是函数,宏不是

函数缺省值:

#include 

using namespace std;

int add(int a=2,int b=1){//从右往左依次赋值,不能跳跃,原因入栈先后顺序
    return a+b;
}

int main()
{
    int a=10,b=20;
    cout << add(a,b) << endl;//结果为:30
    cout << add(a) << endl;//结果为:11,采用缺省
    cout << add() << endl;//结果为:3,采用缺省
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

函数重载:

是函数调用的灵活实现,也是多态的一种(同名函数的不同实现《执行逻辑的不同》)。

底层机制:根据不同的**参数类型,参数个数不同,与返回值无关,函数名相同**,则会在底层的程序的代码段的符号表中生成一个新的函数名,当使用不同的实参调用时,寻找匹配的函数调用。

#include 

using namespace std;

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

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

string add(string a,string b){
    return a+b;
}

//int add(int a,int b,int c=1){
//    return a+b;
//}//与上面的int add(int a,int b)存在二义性,不能同时存在

int main()
{
    cout << add(1,2) << endl;
    cout << add(3.14f,5.12f) << endl;
    cout << add("yao","liang") << endl;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

注意:使用缺省值,注意二义性

引用(quote)

出现原因:避免程序中出现野指针的现象,因为野指针在代码维护中,很难发现问题

底层实现:类型 * const 指针变量 = &变量

#include 

using namespace std;

int add(int * const a,int * const b){
    return *a+*b;
}
int main()
{
    int a=10,b=20;
    cout << add(&a,&b) << endl;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

语法形式:类型名& 引用变量 = 某个变量

#include 

using namespace std;

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

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

int main()
{
    int a=10,b=20;
    cout << add(&a,&b) << endl;
    cout << add(a,b) << endl;
    
    cout << "a的地址:" << &a << endl;//0x4444
    int * const c=&a;
    cout << "c的地址:" << c << endl;//0x4444
    int& c=a;//c没有自己的空间,相当于a的别名,相当于int * const &c = a;
    cout << "c的地址:" << &c << endl;//0x4444
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

引用优点:防止指针传址造成的不良影响,

注意:不要返回局部的返回值,引用作为函数返回值时,可以作为左值使用

#include 

using namespace std;

static int f = 100;

int& add(int& a,int& b){
    f=a+b;
    return f;
}

int main()
{
    int a=10,b=20;
    cout << add(a,b) << endl;//30
    add(a,b)=1000;
    cout << f << endl;//1000
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

指针与引用的对比:

#include 

static int *fun;

int *func(int * const a,int * const b) {
    int sum=*a+*b;
    fun=&sum;
    return fun;
}

int main(int argc, const char *argv[])
{
    /*your code*/
    int x=10,y=20;
    printf("%d\n",*func(&x,&y));
    *func(&x,&y)=100;
    printf("%d\n",*fun);
   return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

实例(数值交换):

#include 

using namespace std;

void swapfunc(int& a,int& b){
    int temp=a;
    a=b;
    b=temp;
}

int main()
{
    int x=10,y=20;
    cout << "x = " << x << ",y = " << y << endl;//x=10,y=20
    swapfunc(x,y);
    cout << "x = " << x << ",y = " << y << endl;//x=20,y=10
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

常引用:

#include 

using namespace std;

string func(const string & s){
//    s="yao";
    return s;
}

int main()
{
    string str="yaoliang";
    cout << "str = " << func(str) << endl;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

总结:

从编译器上:

从语法形式上:

开辟空间

在c中:

int *p=(int *)malloc(sizeof(*p));//申请空间,不初始化
memset(p,0,sizeof(*p));//初始化

升级:
int *q=(int *)calloc(0,sizeof(*q));//申请空间直接初始化

升级:
int *s=(int *)realloc(ptr,sizeof(int)*5);//给申请空间申请空间
realloc()函数将ptr所指向的内存块的大小更改为字节大小。
内容将在区域的开始到新旧大小的最小值的范围内保持不变。
如果新的大小大于旧的大小,则新增的内存将不会初始化。
如果ptr为NULL,那么对于所有size值,调用等价于malloc(size);
如果size等于零,且ptr不为NULL,则调用等价于free(ptr)。
除非ptr为NULL,否则它一定是由之前对malloc()calloc()realloc()的调用返回的。
如果指向的区域被移动,则执行free(ptr)操作。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

failure:NULL;

cpp中:

#include 

using namespace std;

int main()
{
    int *p=new int;//malloc
    cout << *p << endl;  //单纯开辟空间,未初始化

    int *q=new int();//可在括号中指定初始化的值,calloc
    cout << *q <

new是一个函数,里面调用了malloc();delete同,所以delete和delete[]功能相同,区别在于规范

failure:throw()抛出异常,bad_alloc()

注意:

在这里插入图片描述

#include 

using namespace std;

struct stu{
    string _name;
    int _age;
    //结构体或类中的构造函数
    stu(string name ,int age){
        _name=name;
        _age=age;
        cout << "含参构造"  << endl;
    }

    //开辟多个空间
    stu(){
        cout << "无参构造" << endl;
    }

    //结构体或类的析构
    ~stu(){
        cout << "析构" << endl;
    }
};

int main()
{
    stu* s=new stu("yaoliang",19);
    delete s;
    stu * ss=new stu[5];
    delete[] ss;
    return 0;
}
  • 相关阅读:
    案例--某站视频爬取
    【Node.js】模块化:
    stm32单片机之串口通信例程
    方舟开服工具、服务器教程win
    对话 ONES 联合创始人兼 CTO 冯斌:技术管理者如何打造一支自驱型团队?
    微计算机断层扫描的用途以及测试样品要求
    深入探究 JVM 频繁 Full GC 的排查过程
    python html(文件/url/html字符串)转pdf
    List类的超详细解析!(超2w+字)
    为何学linux及用处
  • 原文地址:https://blog.csdn.net/distant_Rove666/article/details/128095288