目录
1.简介
1、C++简介
1、C语言与C++区别?
C语言是一种面向过程的开发语言。 --> 任何一个大的过程都可以拆分为小的过程。
C++是一种面向对象的开发语言。 --> 任何过程都是属于某一个对象上的属性。
2、C++与C语言共同的特点?
C语言使用C语言的语法。
C++除了可以使用C语言的语法之外,还可以使用C++的语法。
3、C++特性?
1)C++中拓展了非常多的数据类型 ->类:特性 封装、继承、多态。
2)C++泛型编程(STL/标准模板库)
2、书写一个C++的helloworld程序。
1、创建一个C++工程文件。
C++工程文件格式是:xxxx.cpp
2、编辑代码。
1)C++兼容C语言,也是从main函数开始执行,从main函数结束。
2)如果要使用C++语法,就必须在文件开头包含头文件以及命名空间。
#include <iostream> //标准头文件
using namespace std; //使用标准命名空间
(在C++中,有很多工具都是放在命名空间std中,如果想在C++代码中直接使用这些工具,那么就必须要使用命名空间)
(如果不使用命名空间,那么使用工具,就必须加上作用域符)
3)C++中使用cout这个工具来输出数据。
4)endl相当于\n
------------------------------
#include <iostream>
using namespace std;
int main(int argc,char *argv[])
{
cout << "helloworld" << endl; //先输出helloworld,然后再换行。
return 0;
}
------------------------------
3、编译代码。
cyz@ubuntu:/mnt/hgfs/C++$ which gcc --> C语言编译器
/usr/bin/gcc
cyz@ubuntu:/mnt/hgfs/C++$ which g++ --> C++编译器
/usr/bin/g++
C语言编译命令: gcc xxx.c -o xxx
C++编译命令: g++ xxx.cpp -o xxx
例如:cyz@ubuntu:/mnt/hgfs/C++/11.8/code$ g++ myfirst.cpp -o myfirst
4、变量。
给一段内存起名,方便我们去操作这片空间。
如何输出一个变量的值?
#include <iostream>
using namespace std;
int main(int argc,char *argv[])
{
int a = 10;
cout << "a = " << a << endl; //a = 10
double b = 3.14;
cout << "b = " << b << endl;
return 0;
}
5、常量。
用于记录在程序中不可修改的数据。
C++记录常量有两种办法:
1)宏常量。
#include <iostream>
using namespace std;
#define DAY 7
int main(int argc,char *argv[])
{
DAY = 8;
cout << "一个星期有:" << DAY << "天" << endl;
return 0;
}
val.cpp:18:6: error: lvalue required as left operand of assignment
//等号左边必须是可以修改的左值。
2)const修饰的变量。
#include <iostream>
using namespace std;
#define DAY 7
int main(int argc,char *argv[])
{
const int month = 12; //常量
month = 13;
cout << "一年有:" << month << "月" << endl;
return 0;
}
val.cpp:23:8: error: assignment of read-only variable ‘month’
//month这个变量是只读的。
六、字符串。
1、字符串作用?
可以在程序中表示一串字符。
2、在C++有两种风格可以表示一个字符串?
C语言风格字符串:
语法:char 数组名[] = "字符串值"
C++风格字符串:
语法:string 字符串变量名 = "字符串值"
#include <iostream>
using namespace std;
int main(int argc,char *argv[])
{
//1. C语言风格字符串
//char str[] = "helloworld";
//cout << "str = " << str << endl;
//2. C++风格字符串
string s = "appletree";
cout << "s = " << s << endl;
return 0;
}
问题一:C语言中,如何判断两个字符串是否一致的? --> 使用strcmp()函数
能不能使用==/>/<来判断? --> 不可以
char *p1 = "hello";
char *p2 = "hello";
if(p1 == p2) --> 这只是判断两个地址,并不是判断两个字符串
{
xxxx
}
问题二:C++中,能不能使用==/>/<来判断?
#include <iostream>
using namespace std;
int main(int argc,char *argv[])
{
string s1 = "helloworld";
string s2 = "hello";
if(s1 == s2)
{
cout << "s1与s2是相同的" << endl;
}
else{
cout << "s1与s2是不相同的" << endl;
}
return 0;
}
七、数据的输入
1、数据的输入作用?
从键盘中获取一些数据,并存放到一个变量中。
2、关键词。
cin
3、语法。
cin >> 变量
#include <iostream>
using namespace std;
int main(int argc,char *argv[])
{
/*
int a = 10;
cout << "a = " << a << endl;
cin >> a; //阻塞从键盘中获取一个数字
cout << "a = " << a << endl;
string s = "hello";
cin >> s;
cout << "s = " << s << endl;
*/
int a;
char b;
cin >> a;
cin >> b; //已经解决了缓冲区的问题,不可以我们自己考虑。
cout << "a = " << a << endl;
cout << "b = " << b << endl;
return 0;
}
八、递增递减运算符
作用:变量的自身+1/-1
符号:++/--
#include <iostream>
using namespace std;
int main(int argc,char *argv[])
{
//1. 前置递增。
int a = 10;
++a;
cout << "a = " << a << endl; //11
//2. 后置递增。
int b = 20;
b++;
cout << "b = " << b << endl; //21
//3. 前置递增与后置递增有什么区别?
//前置递增:先让变量+1,然后再进行表达式运算。
int a2 = 10;
int b2 = ++a2 * 10;
cout << "a2 = " << a2 << endl; //11
cout << "b2 = " << b2 << endl; //110
//后置递增:先进行表达式运算,再自身+1
int a3 = 10;
int b3 = a3++ * 10;
cout << "a3 = " << a3 << endl; //11
cout << "b3 = " << b3 << endl; //100
int a4 = 10;
++(++a4); //允许连续的前置递增。
cout << "a4 = " << a4 << endl; //12
int a5 = 10;
(a5++)++; //不允许连续的后置递增。
cout << "a5 = " << a5 << endl;
return 0;
}
九、内存分区模型。
1、在C++程序执行过程中,将内存大方向划分为4个区域。
1)代码区:存放函数的二进制代码,由操作系统来进行管理。
2)全局区:存放全局变量、静态变量以及常量。
3)堆区:由工程师去分配和释放。若不释放,程序结束时由操作系统来回收。
4)栈区:由编译器自动分配与释放,存放函数形式参数,局部变量等。
十、程序运行前。
在程序编译后,生成一个可执行程序,该程序未执行就已经分为两个区域:
1、代码区。
存放函数二进制代码。 --> 其实就是0101这种数据。
特性一:代码区是共享的。
目的: 对于频繁被执行的代码,只需要在内存中有一份代码即可。
无论执行了多少次程序,都是使用同一份代码。
特性二:代码区是只读的。
原因:防止程序意外地修改了它的指令。
2、全局区。
全局区与静态变量存放在此。
全局区还包含了常量区、字符串常量、其他常量(const修饰的变量)存放在此。
该区域的数据在程序结束之后由操作系统来回收。
#include <iostream>
using namespace std;
//2. 创建全局变量
int g_a = 10;
int g_b = 20;
//5. const修饰的全局变量
const int c_g_a = 10;
const int c_g_b = 20;
int main(int argc,char *argv[])
{
//1. 创建局部变量
int a = 10;
int b = 20;
cout << "&a = " << &a << endl;
cout << "&b = " << &b << endl; //栈区
cout << "&g_a = " << &g_a << endl;
cout << "&g_b = " << &g_b << endl; //全局区
//3. 静态变量
static int s_a = 10;
static int s_b = 20;
cout << "&s_a = " << &s_a << endl;
cout << "&s_b = " << &s_b << endl; //全局区
//4. 常量区
//字符串常量
cout << "string addr = " << &"helloworld" << endl; //全局区
//使用const修饰的变量。
//const修饰的全局变量 const修饰局部变量
//const修饰局部变量 (局部常量)
const int c_l_a = 10;
const int c_l_b = 20;
cout << "&c_l_a = " << &c_l_a << endl;
cout << "&c_l_b = " << &c_l_b << endl; //栈区
cout << "&c_g_a = " << &c_g_a << endl;
cout << "&c_g_b = " << &c_g_b << endl; //全局区
return 0;
}
在全局区:
全局变量
静态变量
const修饰的全局变量
字符串常量
不在全局区:
局部变量
const修饰的局部变量
十一、程序运行后。
栈区:由编译器自动分配释放,存放函数的参数值,局部变量等。
注意:不要返回局部变量的地址,栈区开辟的数据在函数返回时已经释放掉了。
#include <iostream>
using namespace std;
//栈区:不要返回局部变量的地址。
int* func(int val) //val是形式参数,也是属于局部变量,所以val也是栈区开辟空间。
{
int a = 10; //局部变量 --> 栈
return &a; //返回的是局部变量的地址
}
int main(int argc,char *argv[])
{
int *p = func(10);
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
return 0;
}
编译时,出现了一个警告。
stack.cpp:8:6: warning: address of local variable ‘a’ returned [-Wreturn-local-addr]
//编译器温馨提示你:你现在正在返回局部变量的地址。
结果:
cyz@ubuntu:/mnt/hgfs/C++/11.8/code$ ./stack
p = 0
段错误(核心已转储)
问题:为什么p不是等于&a?
正常情况,确实是可以把a的地址返回给p,但是这个地方比较特殊,因为这里返回的是局部变量的地址,由于局部变量空间会释放,系统为了防止你再去访问该局部变量的空间,所以直接返回NULL给p来杜绝这个问题。
堆区:由工程师分配与释放,若不释放,程序结束时由操作系统来回收。
在C++中主要利用new关键词在堆区申请空间。
#include <iostream>
using namespace std;
int *func()
{
//int a = 10; //在栈区开辟空间,函数返回空间会释放。
int *p = new int(10);
return p; //返回时,堆区的空间没有释放掉。
}
int main(int argc,char *argv[])
{
int *p = func();
cout << "p = " << p << endl;
cout << "*p = " << *p << endl; //10
return 0;
}
结果:
cyz@ubuntu:/mnt/hgfs/C++/11.8/code$ ./heap
p = 0x2592c20
*p = 10
十二、new操作符开辟堆空间。
在C++中,利用new操作符在堆区开辟数据。
堆区中开辟的数据,由工程师手动开辟,手动释放,释放利用操作符delete
语法:new 数据类型
利用new创建的数据,会返回该数据对应类型的指针。
1、堆区基本语法。
#include <iostream>
using namespace std;
int *func()
{
//在堆区创建整型数据
int *p = new int(10);
return p;
}
int main(int argc,char *argv[])
{
int *p = func();
cout << "p = " << p << endl; //0x1010
cout << "*p = " << *p << endl; //10
//释放堆区空间。
delete p;
p = NULL; //这句话一般会与delete连用,防止用户再次访问p。
cout << "p = " << p << endl; //0x1010
cout << "*p = " << *p << endl; //0
return 0;
}
2、在堆区利用new开辟数组。
#include <iostream>
using namespace std;
int main(int argc,char *argv[])
{
int *p = new int[10]; // 申请十个int类型的空间
//new int(10); // 申请一个int类型的空间,并把10赋值给这个空间。
//赋值
int i;
for(i=0;i<10;i++)
{
p[i] = i + 100; //100~109
}
for(i=0;i<10;i++)
{
cout << p[i] << endl;
}
delete[] p; //释放数组时,需要加[]才可以。
return 0;
}
十三、引用的基本使用。
1、引用作用?
给变量起别名。
2、语法。
数据类型&别名 = 原名
#include <iostream>
using namespace std;
//引用基本使用
//引用:数据类型 &别名 = 原名
int main(int argc,char *argv[])
{
int a = 10;
//创建引用
int &b = a;
cout << "a = " << a << endl; //10
cout << "b = " << b << endl; //10
b = 100;
cout << "a = " << a << endl; //100
cout << "b = " << b << endl; //100
return 0;
}
十四、引用注意事项。
1、引用必须初始化。
2、引用在初始化之后,不可以改变的。
#include <iostream>
using namespace std;
int main(int argc,char *argv[])
{
//1、引用必须初始化。
//int &c; //编译出错,引用必须要初始化,必须要引用一块合法的空间。
//2、引用在初始化之后,不可以改变的。
int a = 10;
int b = 20;
//创建引用。
int &c = a; //一旦初始化之后,就不可以更改
//一旦c做了a的别名,那么c就不可能是别人的别名了。
//在后续的代码中,c永远永远永远都是a的别名。
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
c = b; //不是让c去做b的别名
//这是一个赋值操作 把b赋值给c
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
return 0;
}
十五、引用做函数参数。
作用:函数传参时,可以利用引用的技术来让形参修饰实参。
#include <iostream>
using namespace std;
//1. 值传递
void mySwap01(int x,int y) //int x=a int y=b
{
int temp = x;
x = y;
y = temp;
}
//2. 地址传递
void mySwap02(int *x,int *y) //int *x = &a int *y = &b
{
int temp = *x;
*x = *y;
*y = temp;
}
//3. 引用传递
void mySwap03(int &x,int &y) // int &x = a int &y = b
{
int temp = x;
x = y;
y = temp;
}
int main(int argc,char *argv[])
{
int a = 10;
int b = 20;
//mySwap01(a,b); //不能调换
//mySwap02(&a,&b); //能调换
mySwap03(a,b); //能调换
cout << "a = " << a << endl; //10
cout << "b = " << b << endl; //20
return 0;
}
总结:当函数参数使用引用传递时,操作形参就等价于操作实参。
十六、引用做函数返回值。
作用:引用可以作为函数返回值存在的。
注意事项:
1、不要返回局部变量的引用。
2、函数调用作为左值的存在。
#include <iostream>
using namespace std;
//注意事项:
//1、不要返回局部变量的引用。
/*
int --> 返回的是10(本体的值)
int& --> 返回的是a(本体)
*/
int& func()
{
//int a = 10; //局部变量
static int a = 10; //静态变量,在函数返回时,并没有释放掉,所以答案就是10
return a; //不能返回局部变量的引用。
}
int main(int argc,char *argv[])
{
int &ret = func();
cout << "ret = " << ret << endl; //10
//2、函数调用作为左值的存在。
func() = 1000;
cout << "ret = " << ret << endl; //1000
return 0;
}