C++的特性

C和C++的区别

首先说一下面向对象和面向过程:

面向过程的思路:分析解决问题所需的步骤,用函数把这些步骤依次实现。
面向对象的思路:把构成问题的事务分解为各个对象,建立对象的目的,不是完成一个步骤,而是描述某个事务在解决整个问题步骤中的行为。
对象是指具体的某一个事物,这些事物的抽象就是类,类中包含数据(成员变量)和动作(成员方法)。
面向对象编程将数据成员和成员函数封装到一个类中,并声明数据成员和成员函数的访问级别(public、private、protected),以便控制类对象对数据成员和函数的访问,对数据成员起到一定的保护作用。而且在类的对象调用成员函数时,只需知道成员函数的名、参数列表以及返回值类型即可,无需了解其函数的实现原理。当类内部的数据成员或者成员函数发生改变时,不影响类外部的代码。

面向对象的三大特性:

  • 封装:将具体的实现过程和数据封装成一个函数,只能通过接口进行访问,降低耦合性。
  • 继承:子类继承父类的特征和行为,子类有父类的非 private 方法或成员变量,子类可以对父类的方法进行重写,增强了类之间的耦合性,但是当父类中的成员变量、成员函数或者类本身被 final 关键字修饰时,修饰的类不能继承,修饰的成员不能重写或修改。
  • 多态:多态就是不同继承类的对象,对同一消息做出不同的响应,基类的指针指向或绑定到派生类的对象,使得基类指针呈现不同的表现方式。

区别:

  1. C是面向过程的语言,是一个结构化的语言,考虑如何通过一个过程对输入进行处理得到输出;C++是面向对象的语言,主要特征是“封装、继承和多态”。封装隐藏了实现细节,使得代码模块化;派生类可以继承父类的数据和方法,扩展了已经存在的模块,实现了代码重用;多态则是“一个接口,多种实现”,通过派生类重写父类的虚函数,实现了接口的重用。

  2. C和C++动态管理内存的方法不一样,C是使用malloc/free,而C++除此之外还有new/delete关键字。

  3. C++支持函数重载,C不支持函数重载

  4. C++中有引用,C中不存在引用的概念

  5. C++ 对 C 的“增强”,表现在以下几个方面:类型检查更为严格。增加了面向对象的机制、泛型编程的机制(Template)、异常处理、运算符重载、标准模板库(STL)、命名空间(避免全局命名冲突)。

  6. 应用领域:C 语言主要用于嵌入式领域,驱动开发等与硬件直接打交道的领域,C++ 可以用于应用层开发,用户界面开发等与操作系统打交道的领域。

  7. 语言自身:C 语言是面向过程的编程,它最重要的特点是函数,通过 main 函数来调用各个子函数。程序运行的顺序都是程序员事先决定好的。C++ 是面向对象的编程,类是它的主要特点,在程序执行过程中,先由主 main 函数进入,定义一些类,根据需要执行类的成员函数,过程的概念被淡化了(实际上过程还是有的,就是主函数的那些语句。),以类驱动程序运行,类就是对象,所以我们称之为面向对象程序设计。面向对象在分析和解决问题的时候,将涉及到的数据和数据的操作封装在类中,通过类可以创建对象,以事件或消息来驱动对象执行处理。

  8. C++ 既继承了 C 强大的底层操作特性,又被赋予了面向对象机制。它特性繁多,面向对象语言的多继承,对值传递与引用传递的区分以及 const 关键字,等等。

Java 和 C++ 的区别

Java 和 C++ 都是面向对象的语言,都支持封装、继承和多态。

二者在语言特性上有很大的区别

  • 指针:C++ 可以直接操作指针,容易产生内存泄漏以及非法指针引用的问题;Java 并不是没有指针,虚拟机(JVM)内部还是使用了指针,只是编程人员不能直接使用指针,不能通过指针来直接访问内存,程序内存更加安全,并且 Java 增加了内存管理机制。
  • 多重继承:C++ 支持多重继承,允许多个父类派生一个类,虽然功能很强大,但是如果使用的不当会造成很多问题,例如:菱形继承;Java 不支持多重继承,但允许一个类可以继承多个接口,可以实现 C++ 多重继承的功能,但又避免了多重继承带来的许多不便。
  • 数据类型和类:Java 是完全面向对象的语言,所有函数和变量部必须是类的一部分。除了基本数据类型之外,其余的都作为类对象,包括数组。对象将数据和方法结合起来,把它们封装在类中,这样每个对象都可实现自己的特点和行为。而 C++ 允许将函数和变量定义为全局的。
  • Java 有自动内存管理垃圾回收机制(GC),不需要程序员手动释放无用内存。
  • C ++同时支持方法重载和操作符重载,但是 Java 只支持方法重载(操作符重载增加了复杂性,这与 Java 最初的设计思想不符)。

垃圾回收:

  • Java 语言一个显著的特点就是垃圾回收机制,编程人员无需考虑内存管理的问题,可以有效的防止内存泄漏,有效的使用空闲的内存。
  • Java 所有的对象都是用 new 操作符建立在内存堆栈上,类似于 C++ 中的 new 操作符,但是当要释放该申请的内存空间时,Java 自动进行内存回收操作,C++ 需要程序员自己释放内存空间,并且 Java 中的内存回收是以线程的方式在后台运行的,利用空闲时间。

应用场景:

  • Java 运行在虚拟机上,和开发平台无关,C++ 直接编译成可执行文件,是否跨平台在于用到的编译器的特性是否有多平台的支持。
  • C++ 可以直接编译成可执行文件,运行效率比 Java 高。
  • Java 主要用来开发 Web 应用。
  • C++ 主要用在嵌入式开发、网络、并发编程的方面。

Python 和 C++ 的区别

  1. 语言自身:Python 为脚本语言,解释执行,不需要经过编译;C++ 是一种需要编译后才能运行的语言,在特定的机器上编译后运行。
  2. 运行效率:C++ 运行效率高,安全稳定。原因:Python 代码和 C++ 最终都会变成 CPU 指令来跑,但一般情况下,比如反转和合并两个字符串,Python 最终转换出来的 CPU 指令会比 C++ 多很多。首先,Python 中涉及的内容比 C++ 多,经过了更多层,Python 中甚至连数字都是 object ;其次,Python 是解释执行的,和物理机 CPU 之间多了解释器这层,而 C++ 是编译执行的,直接就是机器码,编译的时候编译器又可以进行一些优化。
  3. 开发效率:Python 开发效率高。原因:Python 一两句代码就能实现的功能,C++ 往往需要更多的代码才能实现。
  4. 书写格式和语法不同:Python 的语法格式不同于其 C++ 定义声明才能使用,而且极其灵活,完全面向更上层的开发者。

C++的编译过程

编译过程分为四个过程:编译(编译预处理、编译、优化),汇编,链接。

  • 编译预处理:处理以 # 开头的指令;

  • 编译、优化:将源码 .cpp 文件翻译成 .s 汇编代码;

  • 汇编:将汇编代码 .s 翻译成机器指令 .o 文件;

  • 链接:汇编程序生成的目标文件,即 .o 文件,并不会立即执行,因为可能会出现:.cpp 文件中的函数引用了另一个 .cpp 文件中定义的符号或者调用了某个库文件中的函数。那链接的目的就是将这些文件对应的目标文件连接成一个整体,从而生成可执行的程序 .exe 文件。

链接分为两种:

  • 静态链接:代码从其所在的静态链接库中拷贝到最终的可执行程序中,在该程序被执行时,这些代码会被装入到该进程的虚拟地址空间中。
  • 动态链接:代码被放到动态链接库或共享对象的某个目标文件中,链接程序只是在最终的可执行程序中记录了共享对象的名字等一些信息。在程序执行时,动态链接库的全部内容会被映射到运行时相应进行的虚拟地址的空间。

二者的优缺点:

  • 静态链接:浪费空间,每个可执行程序都会有目标文件的一个副本,这样如果目标文件进行了更新操作,就需要重新进行编译链接生成可执行程序(更新困难);优点就是执行的时候运行速度快,因为可执行程序具备了程序运行的所有内容。
  • 动态链接:节省内存、更新方便,但是动态链接是在程序运行时,每次执行都需要链接,相比静态链接会有一定的性能损失。

C++ 11 新特性

  1. auto 类型推导
    auto 关键字:自动类型推导,编译器会在 编译期间 通过初始值推导出变量的类型,通过 auto 定义的变量必须有初始值。
    注意:编译器推导出来的类型和初始值的类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则。

  2. decltype 类型推导
    decltype 关键字:decltype 是“declare type”的缩写,译为“声明类型”。和 auto 的功能一样,都用来在编译时期进行自动类型推导。如果希望从表达式中推断出要定义的变量的类型,但是不想用该表达式的值初始化变量,这时就不能再用 auto。decltype 作用是选择并返回操作数的数据类型。

auto var = val1 + val2; 
decltype(val1 + val2) var1 = 0; 
  • auto 根据 = 右边的初始值 val1 + val2 推导出变量的类型,并将该初始值赋值给变量 var;decltype 根据 val1 + val2 表达式推导出变量的类型,变量的初始值和与表达式的值无关。
  • auto 要求变量必须初始化,因为它是根据初始化的值推导出变量的类型,而 decltype 不要求,定义变量的时候可初始化也可以不初始化。
  1. lambda 表达式
    lambda 表达式,又被称为 lambda 函数或者 lambda 匿名函数。
    lambda匿名函数的定义:
[capture list] (parameter list) -> return type
{
   function body;
};

其中:

  • capture list:捕获列表,指 lambda 所在函数中定义的局部变量的列表,通常为空。
  • return type、parameter list、function body:分别表示返回值类型、参数列表、函数体,和普通函数一样。
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    int arr[4] = {4, 2, 3, 1};
    //对 a 数组中的元素进行升序排序
    sort(arr, arr+4, [=](int x, int y) -> bool{ return x < y; } );
    for(int n : arr){
        cout << n << " ";
    }
    return 0;
}
  1. 范围 for 语句
for (declaration : expression){
    statement
}

参数的含义:

  • expression:必须是一个序列,例如用花括号括起来的初始值列表、数组、vector ,string 等,这些类型的共同特点是拥有能返回迭代器的 beign、end 成员。
  • declaration:此处定义一个变量,序列中的每一个元素都能转化成该变量的类型,常用 auto 类型说明符。
#include <iostream>
#include <vector>
using namespace std;
int main() {
    char arr[] = "hello world!";
    for (char c : arr) {
        cout << c;
    }  
    return 0;
}
/*
程序执行结果为:
hello world!
*/
  1. 右值引用
    右值引用:绑定到右值的引用,用 && 来获得右值引用,右值引用只能绑定到要销毁的对象。为了和右值引用区分开,常规的引用称为左值引用。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    int var = 42;
    int &l_var = var;
    int &&r_var = var; // error: cannot bind rvalue reference of type 'int&&' to lvalue of type 'int' 错误:不能将右值引用绑定到左值上

    int &&r_var2 = var + 40; // 正确:将 r_var2 绑定到求和结果上
    return 0;
}
  1. 标准库 move() 函数
    move() 函数:通过该函数可获得绑定到左值上的右值引用。
int &&rr1 =42;  //正确,字面值常量是右值
int &&rr3 =std::move(rr1);  //OK
  1. 智能指针**
  2. delete 函数和 default 函数
    delete 函数:= delete 表示该函数不能被调用。
    default 函数:= default 表示编译器生成默认的函数,例如:生成默认的构造函数。
#include <iostream>
using namespace std;

class A
{
public:
	A() = default; // 表示使用默认的构造函数
	~A() = default;	// 表示使用默认的析构函数
	A(const A &) = delete; // 表示类的对象禁止拷贝构造
	A &operator=(const A &) = delete; // 表示类的对象禁止拷贝赋值
};
int main()
{
	A ex1;
	A ex2 = ex1; // error: use of deleted function 'A::A(const A&)'
	A ex3;
	ex3 = ex1; // error: use of deleted function 'A& A::operator=(const A&)'
	return 0;
}
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值