C++与C区别概述
C++ 是在 C 语言的基础上发展而来的一门编程语言,它在语法、数据类型、函数、运算符等方面都比 C 语言更为丰富和灵活,同时也具有更好的支持面向对象编程(OOP)的能力,因此被广泛应用于各种系统和应用程序的开发中。以下是 C++ 与 C 语言的一些主要区别:
- 支持面向对象编程:C++ 支持面向对象编程的特性,例如封装、继承、多态等,而 C 语言并不支持。
- 操作符重载:C++ 允许用户对运算符进行重载,即可以自定义运算符的含义和操作对象,而在 C 语言中则不支持此功能。
- 异常处理:C++ 支持异常处理机制,可以捕获和处理程序运行时遇到的异常,而 C 语言则需要通过错误码等方式进行错误处理。
- 标准库:C++ 标准库中包含了大量的库函数和容器,例如 string、vector、map 等,而 C 语言的标准库则比较简单,只包含了常用的库函数。
- 命名空间:C++ 中支持命名空间的概念,可以帮助避免命名冲突的问题,而 C 语言中则不支持。
- 自动类型推断:C++11 引入了自动类型推断关键字 auto 和 decltype,可以根据赋值语句的类型推断出变量的类型,而在 C 语言中则需要手动声明变量类型。
以上只是 C 和 C++ 之间的一些简单区别,实际上它们在很多方面有着类似的语法和特性。对于学习者来说,如果已经掌握了 C 语言,那么学习 C++ 就会比较容易,因为 C++ 的语法和特性可以看作是 C 语言的扩展和补充。接下来我们详细了解一些基础阶段必须要掌握的C++与C的区别。
C++与C的区别详解
C++之C++与C的区别一

动态内存申请
C++中的动态内存申请与C语言中的动态内存申请类似,都需要使用关键字 new 或 malloc 以及相应的类型占位符来分配内存空间,并使用关键字 delete 或 free 来释放内存。但是二者之间也存在一些区别,具体如下:
- 内存分配方式不同:C++ 使用 new 操作符从自由存储区分配连续的内存空间;C 语言使用 malloc 函数从堆上分配一块指定大小的内存空间。
- 内存释放方式不同:C++ 中使用 delete 操作符释放先前用 new 分配的内存空间;释放单个变量内存语法: delete pointer; 释放一段内存基本语法: delete [] pointer; C 语言中使用 free 函数释放先前用 malloc 分配的内存空间。
- 内存类型安全性不同:C++ 中通过使用 new 和 delete 来进行内存分配和释放,其管理机制更加安全、便捷;C 语言中使用 malloc 和 free 时需要对类型进行手动转换,且在对内存进行操作时较容易出现类型错误。
动态内存申请| 申请单个变量内存
在自由存储区创建一个变量,让指针指向该变量。基本语法: type* name = new type; 如下测试代码:
#include <iostream>
int main()
{
int* p1 = (int*)malloc(sizeof(int));
free(p1);
p1 = nullptr;
//申请
int* p2 = new int;
*p2 = 123;
delete p2;
//申请内存并且给予初始化
int* p3 = new int(123);
std::cout << *p3 << std::endl;
delete p3;
return 0;
}
动态内存申请| 申请一段内存
申请一段内存,然后把内存首地址赋值给指针,通过指针偏移实现数据访问,当然直接使用数组下标法使用亦可。基本语法: type* name = new type[size];如下测试代码:
#include <iostream>
int main()
{
//数字类
int* array = new int[3];
for (int i = 0; i < 3; i++)
{
array[i] = i;
std::cout << array[i] << " ";
}
std::cout << std::endl;
//释放一段内存
delete[] array;
//申请并且初始化
array = new int[3] {1, 2, 3};
for (int i = 0; i < 3; i++)
{
std::cout << array[i] << " ";
}
std::cout << std::endl;
//字符串处理
char* pstr = new char[20] { "C++动态内存申请" };
std::cout << pstr << std::endl;
delete[] pstr;
return 0;
}
动态内存申请| 申请一段内存再分配操作
C++允许事先申请内存,然后在已申请的内存上再做分配。基本语法: type* name = new(src) type; 或者 type* name = new(src) type[size];
#include <iostream>
int main()
{
//允许申请的内存做重新分配
char* p = new char[1024];
//new(申请位置) 类型[长度]{初始化};
int* pInt = new(p + 0) int[3] {1, 2, 3};
char* pStr = new(p + 12) char[10] { "再申请" };
for (int i = 0; i < 3; i++)
{
std::cout << pInt[i] << std::endl;
}
std::cout << pStr << std::endl;
delete[] p;
return 0;
}
在C++中,我们可以重载关键字 new 和 delete 来定制内存管理机制,实现自定义的内存分配和释放方式,但是这种做法一般不建议使用,因为过于复杂且容易引起难以诊断的错误。这个后续运算符重载再做详细讲解。
C++类型转换
C++ 中的类型转换分为隐式类型转换和显式类型转换两种方式,所有显式类型转换基本语法: 类型转换操作符<要转换的类型>(转换目标);
- 隐式类型转换:是指程序自动将一种数据类型转换为另一种数据类型,而程序员不需要进行任何操作。例如,整型数据可以自动转换为浮点型数据。
- 显式类型转换:是指程序员通过强制转换的方式将一种数据类型转换为另一种数据类型。在 C++ 中,显示类型转换有以下几种方式:静态转换(static_cast)原始转换(reinterpret_cast)常量转换(const_cast)动态转换(dynamic_cast)
注意:在进行显式类型转换时,应该谨慎使用,避免因类型转换引起的错误。特别是 reinterpret_cast,它的使用范围更小,一定要明确使用场景并慎重对待。
C++类型转换| static_cast
static_cast用于基本数据类型、类继承和派生(后续讲解)、多态上行转换(后续讲解)等在编译时就能确定的类型转换,如下测试代码:
#include <iostream>
int main()
{
//基本数据转换
int num = static_cast<int>(1.3);
//C语言
int c_num = (int)1.3;
//C++
int cpp_num = int(1.3);
void* pNum= #
//指针类型转换
std::cout << *static_cast<int*>(pNum) << std::endl;
//增加const属性
const int& number = static_cast<const int&>(num);
//不能去掉const属性
//以下都报错
//int& test = number;
//int& test = static_cast<int&>(number);
return 0;
}
C++类型转换| const_cast
const_cast用于从标志符中删除 const 属性或者 volatile 属性,或者将常量指针转化为非常量指针。如下测试代码:
#include <iostream>
int main()
{
const int number = 123;
//不能去掉const属性
//以下都报错
//int& test = number;
//int& test = static_cast<int&>(number);
//正确写法
//去掉const属性
int& test = const_cast<int&>(number);
//增加const
int data = 123;
//const_cast增加const属性只能用于指针或者引用
//以下两种错误
//const int num = const_cast<const int>(data);
//const int num = const_cast<const int>(data);
const int& num = const_cast<const int&>(data);
return 0;
}
C++类型转换| reinterpret_cast
指针之间的转换,不进行任何类型检查,仅仅进行比特位的重新解释,以及类型转换时让编译器执行非常规的位操作。如下测试代码:
#include <iostream>
void print()
{
std::cout << "reinterpret_cast" << std::endl;
}
int main()
{
//错误代码
//int num = print;
//指针转整数
long long num = reinterpret_cast<long long>(print);
std::cout << num << std::endl;
//整数转指针
typedef void(*Func)();
auto pFunc = reinterpret_cast<Func>(num);
pFunc();
return 0;
}
C++类型转换| dynamic_cast
用于在运行时进行多态类型转换。(后续讲解)
C++结构体类型
后续C++类中的大部分内容C++结构体都可以使用,C++结构体就可以当作类去使用,例如类中如下操作结构体都可以完成:
- 构造函数
- 析构函数
- 继承
- 多态
- 特殊成员
- 重载
- this指针
目前了解简单区别即可。
C++结构体| 类型上改变
C++结构体在使用类型的时候不在需要struct关键字了,直接使用结构体名即可,如下测试代码:
#include <iostream>
struct MM
{
char name[20];
int age;
};
int main()
{
//C语言
struct MM mm = { "baby",18 };
//cpp
MM girl = { "girl",20 };
//new一个MM
MM* pMM = new MM;
return 0;
}
C++结构体| 成员上改变
C++结构体即可以包含数据成员,也可以包含函数成员,通常结构体中的函数可以叫做成员函数。访问方式和数据成员访问方式一样,如下测试代码:
#include <iostream>
struct MM
{
char name[20];
int age;
void print()
{
std::cout << name << " " << age << std::endl;
}
};
int main()
{
MM mm = { "baby",18 };
mm.print();
return 0;
}
C++结构体| 结构体中声明,结构体外实现的函数
C++结构体中声明函数,结构体外实现函数需要用 结构体名:: 限定,如下测试代码:
#include <iostream>
struct MM
{
char name[20];
int age;
void print();
};
//外面实现需要结构体名限定
void MM::print()
{
std::cout << name << " " << age << std::endl;
}
int main()
{
MM mm = { "baby",18 };
mm.print();
return 0;
}
C++string类型
C++string 类型本质是一个类类型,所以目前暂时掌握一些常用使用方式即可,无需追究那么多原因,后续类和对象所有内容学完,可以尝实现一个简单string类玩玩。
C++string类型| 声明和初始化
C++string的声明和初始化比较简单,使用string类型的时候记得包含头文件: #include<string> ; 他和string.h 或者cstring 是有区别的,如下代码:
#include <iostream>
#include <string>
int main()
{
std::string str1;
std::string str2("string");
std::string str3 = "string";
std::string str4 = str3;
std::string str5(str3);
return 0;
}
C++string类型| 遍历
C++string不能直接用C语言printf函数和字符串处理函数直接操作,需要调用c_str或者data函数去使用,C++中可以直接cout与cin直接操作,当然也可以直接支持下标访问单个字符。如下测试代码:
#include <iostream>
#include <string>
#include <cstring>
int main()
{
//下标法访问
std::string str = "coolmoying";
for (int i = 0; i < str.size(); i++)
{
std::cout << str[i];
}
std::cout << std::endl;
//at函数下标法
for (int i = 0; i < str.size(); i++)
{
std::cout << str.at(i);
}
std::cout << std::endl;
//区间遍历
for (auto v : str)
{
std::cout << v;
}
std::cout << std::endl;
//C语言操作
std::printf("%s\n", str.c_str());
std::puts(str.data());
//迭代器遍历 后续讲解
std::string::iterator iter;
for (iter = str.begin(); iter != str.end(); iter++)
{
std::cout << *iter;
}
std::cout << std::endl;
return 0;
}
C++string类型| 字符串比较与连接
C++string的比较直接使用运算符即可,连接直接是用+运算符即可,当然也可以采用调用函数的方式,如下测试代码:
#include <iostream>
#include <string>
#include <cstring>
int main()
{
//判断
std::string str1 = "moolying";
std::string str2 = "coolmoying";
std::cout << (str1 == str2) << std::endl;
std::cout << (str1 < str2) << std::endl;
std::cout << (str1 > str2) << std::endl;
std::cout << (str1 != str2) << std::endl;
std::cout << (str1 <= str2) << std::endl;
//调用函数的形式
//类似strcmp
bool result = str1.compare(str2);
//连接
std::string str3 = str1 + str2;
std::cout << str3 << std::endl;
std::cout << str1 << std::endl;
//函数的形式会更改原来的字符串
std::cout << str1.append(str2) << std::endl;
std::cout << str1 << std::endl;
return 0;
}
C++string类型| 其他函数操作
C++string中含有大量的成员函数,有兴趣的可以查看MSDN帮助文档,这里简单实用常用一些函数。如下测试代码:
#include <iostream>
#include <string>
#include <cstring>
int main()
{
std::string str= "moolying";
//长度
std::cout << "size:" << str.size() << std::endl;
std::cout << "length:" << str.length() << std::endl;
//插入字符
str.insert(str.begin(), 'A');
//尾部插入
str.push_back('D');
//end():结束位置不是最后一个元素的位置
std::cout << "第一个字符:" << str.front() << std::endl;
std::cout << "第一个字符:" << *str.begin() << std::endl;
std::cout << "最后一个字符:" << str.back() << std::endl;
std::cout << "最后一个字符:" << *(str.end() - 1) << std::endl;
//str="coolmoying";
std::cout << "查字串:" << str.find("ying") << std::endl;
//substr(起始下标,截取个数);
std::cout << "截取:" << str.substr(4, 2) << std::endl;
return 0;
}
C++string类型| 其他
C++提供一个to_string 可以把数字转换为字符串,如下测试代码:
#include <iostream>
#include <string>
int main()
{
std::cout << std::to_string(1.111) << std::endl;
std::string request = "request " + std::to_string(12.13) + "\r\n";
std::cout << request << std::endl;
return 0;
}
相关
如果阁下正好在学习C/C++,看文章比较无聊,不妨关注下关注下小编的视频教程,通俗易懂,深入浅出,一个视频只讲一个知识点。视频不深奥,不需要钻研,在公交、在地铁、在厕所都可以观看,随时随地涨姿势。