首页 > 编程语言 >C++学习day01

C++学习day01

时间:2023-08-22 20:22:10浏览次数:35  
标签:int day01 namespace C++ 学习 内存 类型 new

C++学习day01

一、C++介绍

本贾尼.斯特劳斯特卢普,于1979年在贝尔实验室负责分析UNIX系统内核流量的分布情况时,特别希望有一种更加模块化的工具,于1979.10开始着手研发一款新的编程语言,在C语言的基础上增加了面向对象的机制,也就是C++,1983年完成了C++的第一个版本

C++与C的关联和重要区别:(面试题)

1、C++完全兼容C语言的所有内容
2、支持面向对象的编程思想
3、支持运算符重载、函数重载的编译时多态机制
4、泛型编程、模版编程
5、支持异常处理
6、类型检查更加严格
注意:学习C++目前重点学习是面向对象的编程思想,而不是各种花里胡哨的语法

二、第一个C++程序

#include <iostream>
using namespace std;
int main(int argc,const char* argv[])
    {
        cout << "Hello World!" << endl;
        return 0;
    }

1、文件扩展名由 .c 变成.cpp .cc .C .cxx

2、编译器由gcc变成g++,gcc也可以继续使用,需要增加编译参数
-xC++ -lstdc++
3、C++语言的标准头文件不带.h,iostream意为in out stream,在C++中输入、输出被封装成了流操作,C语言的头文件还可以继续使用,但是标准C的头文件建议名字换成前面加c 后缀去掉的新名字 例如 cstdio,为了删除原C标准头文件中的大量的宏,重新放入名字空间中,防止命名冲突
4、C++的输入、输出

cout 用于输出 
cin  用于输入  

不需要占位符,会自动识别数据类型
printf/scanf 属于C标准库中的函数
cout/cin 是C++标准库中的类对象

5、增加了名字空间机制,是C++为了解决命名冲突而发明的一项机制

三、 C++与C数据类型的不同

1、结构的不同

#include <iostream>
using namespace std;

struct Student
{
	char name[20];
	char sex;
	int id;
protected:
	void func(int num)
	{
		cout << "我是Student的成员函数" << id << endl;	
	}
	Student(void)
	{
		cout << "我是Student的构造函数" << endl;	
	}
};

int main(int argc,const char* argv[])
{
	Student stu;	
//	stu.id = 10086;
	stu.func(100);
}

①、不再需要通过typedef来缩短结构类型名,在C++中设计好结构后,定义结构类型时不再需要使用struct关键字了
②、结构中可以有成员是成员函数、成员变量,结构变量、结构指针,使用 . 和 -> 访问成员,如果是成员函数,那么可以直接访问同结构中的任何成员,不需要.和->
③、结构中有一些隐藏的成员函数:构造函数、析构函数、拷贝构造、赋值操作
④、结构可以继承其它结构,也可以被其他结构所继承
⑤、可以给成员赋予访问控制属性

    public    公开的(默认) 
    protected 保护的 结构内和继承了它的结构中能使用 
    private   私有的 只有结构中才能使用

2、联合的不同

①、不再需要通过typedef来缩短联合类型名,在C++中设计好联合后,定义联合类型时不再需要使用union关键字了
②、联合中可以有成员是成员函数、成员变量,联合变量、联合指针使用 . 和 -> 访问成员,如果是成员函数,那么可以直接访问同联合中的任何成员,不需要.和->
③、联合中有一些隐藏的成员函数:构造函数、析构函数、拷贝构造、赋值操作
④、可以给成员赋予访问控制属
public 公开的(默认)
protected 保护的 结构内和继承了它的结构中能使用
private 私有的 只有结构中才能使用

3、枚举的不同

  • C:(不是很严格)

    #include <stdio.h>
    
    enum Key{UP=183,DOWN,RIGHT,LEFT};
    
    int main(int argc,const char* argv[])
    {
    	enum Key k = 100;
    	printf("%d\n",k);
    }
    
  • C++(很严格)

#include <iostream>
using namespace std;

enum Key{UP=183,DOWN,RIGHT,LEFT};

int main(int argc,const char* argv[])
{
	Key k = 183;	//false
	k = UP;
	cout << k << endl;
}

①、不再需要通过typedef来缩短枚举类型名,在C++中设计好枚举后,定义枚举类型时不再需要使用enum关键字了
②、C++编译器会对枚举的值进行检查,如果不符合就报错
③、C语言使用整型来模拟的,C++中的枚举类型是一种真正的数据类型,所以不能与整型进行隐式类型转换了

4、布尔类型的不同

#include <iostream>
using namespace std;

int main(int argc,const char* argv[])
{
	bool flag = true;	
	flag = 0;

	cout << sizeof(true) << endl;
	cout << flag << endl;
}

①、C++中有真正的布尔类型,bool、true、false 是C++的关键字,不再需要包含 stdbool.h 头文件
②、true、false 在C++中是1字节,而C语言是4字节(int)
注意:无论C还是C++,bool类型变量只能存储0|1

5、字符串的不同

#include <iostream>
using namespace std;

int main(int argc,const char* argv[])
{
	const char* p = "hehe";
	string str = p;
	if("heh" == str)
	{
		str = "xixixhe";
	}
	str += "haha";
	
	cout << str << " " << str.length() << " " << str.size() <<  endl;
}

①、C++中的字符串被封装成了 string 类,可以与C语言的字符串进行转换
②、string类被封装在 string 文件,并属于std名字空间,但是string已经被iostream包含
③、使用string类,可以通过运算符的方式直接操作字符串,但是C语言string.h中的str系列函数也可以继续使用

=   strcpy
+=  strcat
==  strcmp  相同为真

size() \ length() strlen 只算字符个数,不计算'\0'

④、C++中没有规定string类必须以'\0'结尾,编译器在实现时可以在结尾加上'\0'也可以不加,由编译器决定,因为string是一个类,它的长度信息已经被封装记录在私有成员变量中了

6、void*的不同

#include <iostream>
#include <cstdlib>
using namespace std;

int main(int argc,const char* argv[])
{
	int* p = (int*)malloc(4);
	void* p1 = p;
}

在C语言中,void类型可以与任意类型的指针进行自动转换,而在C++中,void类型不可以自动转换成其他任意类型的指针,如果需要把void类型的指针赋值给其他类型的指针时,必须通过强制类型转换后才能赋值,提高指针数据类型的安全性
但是其他类型的指针还是可以自动转换成void类型的指针,因为C语言标准库、系统函数中采用了大量的void类型作为参数,如果不保留这个方式会导致C++在调用这些函数时非常麻烦

int* p = (int*)malloc(4);

四、名字空间

1、使用名字空间的原因

由于C++完全兼容C语言,C++标准库中自带大量的类、函数、宏,而且支持继承语法,导致全局的标识符大量增加,因此命名冲突的概率极大的增加,因此名字空间就是为了解决命名冲突

2、什么是名字空间

是C++中一种对命名空间进行逻辑划分的一种技术

namespace xxx
        {
            变量;
            函数;
            结构、联合、枚举;
            类;
            ...
        }

定义了名字空间后形成了一个相对封闭的作用域空间

3、如何使用

  • 直接导入

     using namespace xxx;
    

之后就可以直接使用名字空间中的所有内容,虽然方便,实际工作中不建议

  • 域限定符 ::

    xxx::标识符
    

实例:

#include <iostream>
using namespace std;

int num = 50;

namespace n1{
	int num = 100;	
}

namespace n2{
	int num = 200;	
}

//using namespace n1;
//using namespace n2;

int main(int argc,const char* argv[])
{
	int num = 10;
	cout << n1::num << endl;	//100
	cout << ::num << endl;        //50
	cout << n2::num << endl;	//200
}

4、名字空间可合并

名字空间可以被多次定义,不同位置的名字空间编译器会在编译时自动合并

a.cpp
        namespace n1{int a;}
b.cpp
        namespace n1{int b;}
main.cpp
        using namespace n1;//  会把a、b都导入进来

5、名字空间中的声明和定义可以分开

a.h
     namespace n1{
            extern int num;
        }
a.cpp
        int n1::num;

注意:可以分开定义,但是必须加上 名字空间名::变量名

6、匿名名字空间

所有全局标识符都归属于同一个名字空间,称为匿名名字空间,可以通过 ::全局标识符 来指定访问匿名名字空间中的内容
例如:同名的全局变量被同名局部变量屏蔽后,可以以此指定访问全局变量

7、名字空间可以嵌套

namespace n1{ 
        int num = 10; 
        namespace n2{ 
            int num = 20; 
            namespace n3{ 
                int num = 30;   
            }
        }   
    }
  • 采用逐层分解访问

    n1::n2::n3::num  
    
  • 导入指定层的名字空间

 using namespace n1::n2;

实例:

#include <iostream>
using namespace std;

namespace n1{
	int num = 10;
	namespace n2{
		int num = 20;
		namespace n3{
			int num = 30;	
		}
	}
}

using namespace n1::n2;
int main(int argc,const char* argv[])
{
	cout << n1::n2::n3::num	<< endl;    //30
	cout << n3::num << endl;        //30
	cout << num << endl;        //20
}

8、可以给名字空间的名字取别名

namespace n123 = n1::n2::n3

五、C++的堆内存管理new/delete

1、申请和释放的语法格式

C++中有专门用于管理堆内存的语句,而C语言中只能使用标准库提供的函数

  • new
类型* p = new 类型名;
            new 分配内存,相当于C语言的malloc   

内存分配失败:

malloc分配内存失败会返回NULL;

new分配内存失败会抛出一个异常std::bad_array_new_length,如果不接异常并处理,那么会终止

返回值:

malloc返回一个void*类型的指针
 new返回一个对应类型的指针

  • delete
 delete p;   
            delete 释放内存 相当于C语言的free(p)

重复释放问题:delete可以释放空指针,但是也不能重复释放其他有效地址,与free一致

2、初始化

new 允许在分配内存时直接初始化内存

 类型* p = new 类型名(val);
 int* p = new int(10);

3、连续内存的申请和释放

  • 申请:
 类型* p = new 类型名[个数];
 int* p = new int[10];//10个int类型的连续堆内存40字节            

new[ ] 会多次调用构造函数

  • 释放:

    delete[] p;
    

delete[ ]专门用于释放通过 new[ ] 申请出来的内存
delete[ ]也会多次调用析构函数

  • new/delete 不能与 malloc/free 混合使用

    int* p = new int;
    free(p);
    

虽然语法允许,但是不能这样混合使用
因为使用new分配内存时,会自动调用结构、联合、类类型的构造函数,使用delete释放内存时,会自动调用结构、联合、类类型的析构函数
但是malloc和free都不会调用,如果混用,就会导致构造、析构没有对应调用。

malloc/free new/delete new[]/delete[] 都不能混用。

通过new[]为结构、联合、类类型申请的内存的前4字节中记录了申请的次数,这样就可以让编译器知道需要调用多少次构造函数和析构函数

4、malloc/free 和 new/delete 的区别?

malloc/free new/delete
身份 函数 关键字/运算符
返回值 void* 对应类型指针
参数 字节个数(手动计算) 类型(自动计算)
连续内存分配 手动计算总字节数 new[个数]
扩容 realloc 无法直接处理
失败 返回NULL 抛异常
构造/析构函数 不调用 调用
初始化 不能初始化 可以初始化
头文件 stdlib.h 不需要
函数重载 不允许 允许
内存分配位置 堆内存 自由区内存

注意:自由存储区是一个抽象的概念,而不是具体某个位置段,平时一般称new是分配在堆内存也问题不大,因为new底层默认调用了malloc,所以此时称分配在堆内存没问题,但是new可以像运算符一样被程序员重载或借助 new(地址) 类型 两种方式分配内存时,可以分配到其他内存段,所以称为自由存储区

笔试题练习

现在有一块已经分配好的内存(堆、栈) 如何让通过new新申请的类对象、结构变量使用这块内存?

#include <iostream>
using namespace std;

struct Student
{
	char name[20];
	char sex;
	int id;

	Student()
	{
		cout << "我是构造函数" << endl;	
	}
};

int main(int argc,const char* argv[])
{
	cout << sizeof(Student) << endl;
	char arr[28] = {};
	Student* stu = new(arr) Student;
	cout << &arr << " " << stu << endl;
}

输出:28
我是构造函数
0xbfaf5820 0xbfaf5820

标签:int,day01,namespace,C++,学习,内存,类型,new
From: https://www.cnblogs.com/ljf-0804/p/17649601.html

相关文章

  • 算法学习-exKMP
    什么是exKMPexKMP(Z-Algorithm)是一个可以在\(O(|S|+|T|)\)的时间复杂度内求出\(T\)串的每个后缀与\(T\)的LCP(最长公共前缀)\(T\)串和\(S\)串每个后缀的LCP。的算法。算法过程首先回忆一下KMP算法,求\(nxt\)数组和两串匹配本质上没啥区别。所以我们尝试也将......
  • [算法学习笔记] O(nlogn)求最长上升子序列
    朴素dp求最长上升子序列大家应该都会朴素dp求最长上升子序列,简单回忆一下。我们令\(f_i\)表示以第\(i\)位元素为结尾的最长上升子序列长度。满足\(\forallj<i\),则有:\(f_i=max(f_i,f_j+1)[a_j<a_i]\)Explanation:\(a_i\)前面若有多个可以拼接的序列,则拼一个......
  • ACM MM 2023 | 腾讯优图实验室6篇论文入选,含视觉识别、半监督学习等研究方向
    前言 近日,腾讯优图实验室6篇论文被国际人工智能多媒体领域顶级会议ACMMM2023(ACMInternationalConferenceonMultimedia)所接收,涵盖视觉识别、神经绘画和风格化研究、半监督学习等多个研究方向,进一步展示了腾讯优图实验室在人工智能领域的技术能力和学术成果。ACMMM是计算机......
  • openGauss学习笔记-47 openGauss 高级数据管理-权限
    openGauss学习笔记-47openGauss高级数据管理-权限数据库对象创建后,进行对象创建的用户就是该对象的所有者。数据库安装后的默认情况下,未开启三权分立,数据库系统管理员具有与对象所有者相同的权限。也就是说对象创建后,默认只有对象所有者或者系统管理员可以查询、修改和销毁对象,......
  • SQL注入基础学习4
    14、第14关测试注入点,查找闭合方式,闭合方式为"查找数据库admin"and1=updatexml(1,concat(0x7e,(selectdatabase())),3)#/*结果如下*/XPATHsyntaxerror:'~security'查找数据库中的表admin"and1=updatexml(1,concat(0x7e,(selectgroup_concat(table_name)f......
  • 【笔记】机器学习基础 - Ch5. Support Vector Machines
    5.1Linearclassification考虑如下问题:\(\mathbb{R}^N\)上的\(\calX\)服从某个未知分布\(\calD\),并由目标函数\(f:\calX\toY\)映射到\(\{-1,+1\}\)。根据采样\(S=(({\bfx}_1,y_1),\dotsb,({\bfx}_m,y_m))\)确定一个二分类器\(h\in\calH\),使得其泛化......
  • JavaSE学习笔记
    Java基础数据类型扩展及面试题讲解整数拓展: 进制、二进制0b、十进制、八进制0、十六进制0x浮点数拓展:银行业务怎么表示?钱——最好完全避免使用浮点数进行比较使用BigDecimal数学工具类float:有限、离散、舍入误差、大约、接近但不等于double:精度问题字符拓......
  • 标准C++ -- day02
    一、函数重载什么是函数重载在同一作用域下,函数名相同,参数列表不同的函数构成重载关系函数重载与返回值类型、参数名无关与作用域是否相同,以及参数列表的数量、参数类型、常属性不同等有关#include<iostream>usingnamespacestd;voidfunc(intnum){cout<<"i......
  • day01
    一、进程间通信-socket套接字  基本特征:socket是一种接口技术,被抽象成一种文件的操作,可以让同一计算机中的不同进程之间通信,也可以让不同计算机中的进程进行通信(网络通信)    本地进程间通信编程模型:        进程A         ......
  • Python学习日记 2023年8月22日
    importglobimportargparseimportcv2importnumpyfromtqdmimporttqdmfromitertoolsimportproductdefparsArgs():parser=argparse.ArgumentParser('拼接马赛克图片')parser.add_argument('--targetpath',type=str,default='3.jp......