首页 > 编程语言 >标准C++ -- day01

标准C++ -- day01

时间:2023-08-22 09:11:44浏览次数:40  
标签:-- day01 namespace C++ int 内存 类型 new

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

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

    public        公开的(默认)
    protected     保护的  联合内和继承了它的联合中能使用
    private       私有的  只有联合中才能使用
    
  3. 枚举的不同
    a、不再需要通过typedef来缩短枚举类型名,在C++中设计好枚举后,定义枚举类型时不再需要使用enum关键字了
    b、C++编译器会对枚举的值进行检查,如果不符合就报错
    c、C语言使用整型来模拟的,C++中的枚举类型是一种真正的数据类型,所以不能与整型进行隐式类型转换了

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

  5. 字符串的不同
    a、C++中的字符串被封装成了 string 类,可以与C语言的字符串进行转换
    b、string类被封装在 string 文件,并属于std名字空间,但是string已经被iostream包含
    c、使用string类,可以通过运算符的方式直接操作字符串,但是C语言string.h中的str系列函数也可以继续使用
    = strcpy
    += strcat
    == strcmp 相同为真
    size() \ length() strlen 只算字符个数
    d、C++中没有规定string类必须以'\0'结尾,编译器在实现时可以在结尾加上'\0'也可以不加,由编译器决定,因为string是一个类,它的长度信息已经被封装记录在私有成员变量中了

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

    int* p = (int*)malloc(4);
    
四、名字空间
  1. 为什么需要名字空间
    由于C++完全兼容C语言,C++标准库中自带大量的类、函数、宏,而且支持继承语法,导致全局的标识符大量增加,因此命名冲突的概率极大的增加,因此名字空间就是为了解决命名冲突

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

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

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

  1. 如何使用
    1)直接导入

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

    2)域限定符 ::

    xxx::标识符
    
  2. 名字空间可合并
    名字空间可以被多次定义,不同位置的名字空间编译器会在编译时自动合并
    a.cpp
    namespace n1{int a;}
    b.cpp
    namespace n1{int b;}
    main.cpp
    using namespace n1;// 会把a、b都导入进来

  3. 名字空间中的声明和定义可以分开
    a.h
    namespace n1{
    extern int num;
    }
    a.cpp
    int n1::num;
    注意:可以分开定义,但是必须加上 名字空间名::变量名

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

  5. 名字空间可以嵌套

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

    采用逐层分解访问
    n1:: n2:: n3::num
    导入指定层的名字空间
    using namespace n1::n2;

  6. 可以给名字空间的名字取别名
    namespace n123 = n1:: n2::n3

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

    语法格式:
        类型* p = new 类型名;
            new 分配内存,相当于C语言的malloc   
        delete p;   
            delete 释放内存 相当于C语言的free(p)
    
  2. new 允许在分配内存时直接初始化内存

        类型* p = new 类型名(val);
        int* p = new int(10);
    
  3. new/delete 不能与 malloc/free 混合使用

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

        类型* p = new 类型名[个数];
            int* p = new int[10];//10个int类型的连续堆内存40字节
            new[] 会多次调用构造函数
        delete[] p;
            delete[]专门用于释放通过 new[] 申请出来的内存
            delete[]也会多次调用析构函数
        注意:malloc/free  new/delete  new[]/delete[] 都不能混用
        注意:通过new[]为结构、联合、类类型申请的内存的前4字节中记录了申请的次数,这样就可以让编译器知道需要调用多少次构造函数和析构函数
    
  5. 重复释放问题
    delete可以释放空指针,但是也不能重复释放其他有效地址,与free一致

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

  7. 返回值类型不同
    malloc返回一个void* 类型的指针
    new返回一个对应类型的指针
    重点掌握面试题: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;
}

标签:--,day01,namespace,C++,int,内存,类型,new
From: https://www.cnblogs.com/bigflyny/p/17647580.html

相关文章

  • 1、Docker 安装 Jenkins
    更多参考:Jenkins官网#拉取Jenkins镜像dockerpulljenkins/jenkins#运行容器dockerrun-d-p8080:8080-p50000:50000jenkins/jenkins#访问,有初始化页面http://localhost:8080#获取初始页面需要的密码<container_id>运行的容器iddockerexec-it<container_i......
  • Interval GCD 题解 || WHK废物快乐题
    题意给定一个序列,需要对其进行区间加和和查询\(\gcd\)操作。思路首先看到了区间加和,自然想到是直接打懒标记,但是呢。。。\(\gcd\)具有一些特殊性,我们并不能通过向下传递标记的方式维护\(\gcd\)。于是想到昨天Tad讲树状数组区间修改的差分数组方案。我们创建一个数组......
  • 「Note」数据结构方向 - 数据结构进阶
    1.平衡树咕咕咕2.树套树咕咕咕3.LCT3.1.介绍3.1.1.基本概念LCT全名Link-Cut-Tree,动态树,是用来维护动态森林的数据结构。它支持以下操作(需要保证任意操作时刻维护的都为森林):连边。断边。换根。提取路径信息。LCT的大体思路是将每棵树拆分为若干条链,并用平衡......
  • abc232e Rook Path
    开始看成走到相邻格子,后面发现是车的走法。。。发现可以将整个图分成四个部分,(x1,y1)\((x,y1)(x\neqx1)\)\((x1,y)(y\neqy1)\)\((x,y)(x\neqx1,y\neqy1)\)然后每一部分中的点的答案都是相同的,转移即可。#include<algorithm>#include<cstdio>#include<cstring>#......
  • 解放生产力orm并发更新下应该这么处理求求你别再用UpdateById了
    解放生产力orm并发更新下应该这么处理求求你别再用UpdateById了背景很多时候为了方便我们都采用实体对象进行前后端的数据交互,然后为了便捷开发我们都会采用DTO对象进行转换为数据库对象,然后调用UpdateById将变更后的数据存入到数据库内,这样的一个做法有什么问题呢,如果你的......
  • Service(服务)
    目录k8s的三层网络修改service命令方式修改servicecore-api-service.ymalk8s的三层网络宿主机网络物理主机网络。svc集群网络clusterIp集群网络,集群内部服务可以相互访问,集群外部不能访问集群内的服务。可以升级为NodePort方式,映射podIp:podPort到宿主机的IP和端口,这样......
  • IDEA配置Git仓库
          在.gitignore中配置忽略文件内容  **/target/.idea*.iml*.class*Test.java**/test/创建git本地仓库 点击后,选择项目主目录文件夹完成后出现如下界面,点提交 左侧出现如下界面 点commit,接下来如果弹窗提醒,继续点commit创建远程仓库  创......
  • 「学习笔记」扩展 KMP(Z 函数)
    对于个长度为\(n\)的字符串\(s\)。定义\(z[i]\)表示\(s\)和\(s[i,n-1]\)(即以\(s[i]\)开头的后缀)的最长公共前缀(LCP)的长度。\(z\)被称为\(s\)的Z函数。这里注意,在Z函数中,\(z[0]=0\),但是根据LCP的定义,\(z[0]=n\),具体应该为何值,根据题目意思来判断。本文更偏......
  • 【Boost】boost.log 要点笔记
    常用简写:namespacelogging=boost::log;namespacesrc=boost::log::sources;namespaceexpr=boost::log::expressions;namespacesinks=boost::log::sinks;namespaceattrs=boost::log::attributes;namespacekeywords=boost::log::keywords;要点:结构图要牢......
  • 控件背景颜色设置为透明的方法
    引言在项目开发中,有时需要将控件的背景颜色设置为透明,比如label控件。那么,如何将控件的背景颜色设置为透明呢?是否只需将控件的BackColor属性设为Transparent即可呢?答案是否定的。想要解决这个问题,首先要了解在C#中什么叫做透明。this.TransparencyKey=Color.Red;this......