6_数组_指针_字符串
数组-指针-字符串
数组
数组的定义与初始化
- 类型符 数组名[常量表达式];
- 数组必须先定义,再使用
- 数组名字是数组首元素的内存地址,是一个常量,不能被赋值
- 数组可以作为函数的参数:形参会影响实参,一般数组长度也要作为参数传入
- 对象数组
int a[10]; //定义整形一维数组
int a[2][5]; //定义整形二维数组
Point a[2]; //定义Point类对象数组
int a[10]={0,1,2,3}; //初始化
int a[]={0,1,2}; //编译器根据初始化的元素确定数组大小
Point a[2] = {Point(1,2), Point(3,4)}; //初始化
int a[2][2]={{1},{3,4}}; //二维初始化
//作为函数的参数
#include <iostream>
using namespace std;
void add(int a[], int b[], int len_a, int len_b){
for(int i=0;i<len_a;i++){
a[i] = a[i] + b[i];
}
}
int main(){
int a[3] = {1,2,3};
int b[3] = {4,5,6};
add(a, b, 3, 3);
for(int i=0; i<3;i++){
cout << a[i] << endl;
}
return 0;
}
基于范围的for循环
int main(){
int a[3] = {1,2,3};
int *p;
for(p = a; p < a + sizeof(a)/sizeof(int);p++){
cout << *p << endl;
}
return 0;
}
int main(){
int a[3] = {1,2,3};
for(int & e:a){ //遍历容器,需要C++11标准
cout << e << endl;
}
return 0;
}
vector
vector<int> arr(5); //建立大小为5的int数组
arr.size(); //返回元素个数
arr[0];
add(vector<int> &v1, vector<int> &v2);
指针
指针的定义
- 本质为内存地址,间接访问存储单元
- 指针运算符 * 和 地址运算符 &
- *指向常量的指针 const int p = &a 不可以通过指针改变所指的对象
- 指针类型的常量 int * const p2 = &a p2的值不能更改,p2不能再指向别的对象
- 指针运算
int i=0, j=1;
int *p = &i; //指针p指向i
int *p; p = &i; //指针p指向i
int *p = nullptr; //定义空指针,int *p = 0
int void *p; //可以被赋予任何类型对象的地址;只能用于存放地址,不能通过它访问对象的值(可以先强制转换再访问)
*p = 3; //通过指针间接更改i
int *p2 = &b;
p = p2; //指针赋值
p = p + 1; //指针向后方移动一个数据的大小,即指向下一个数据
指针与数组
int a[10];
int *p;
pa=&a[0]; pa = a; //指针指向数组
//*p=a[0] *(pa+1)=a[1]
指针数组
- 数组的元素为指针类型
int line1[] = {1,0,0};
int line2[] = {0,1,0};
int line3[] = {0,0,1};
int *p[3] = {line1, line2, line3}
指针与函数
- 指针作为函数的参数:双向传递, 数组太大
- 指针类型的函数 int* add(int, int)
指向函数的指针
存储类型 数据类型(*函数指针名)(形参列表)
典型用途:函数的回调(将函数指针作为函数的参数传递)
#include <iostream>
#include "point.h"
using namespace std;
int compute(int a, int b, int(*func)(int, int))
{return func(a,b);}
int max(int a, int b)
{return ((a > b) ? a: b);}
int min(int a, int b)
{return ((a < b) ? a: b);}
int sum(int a, int b)
{return a+b;}
int main(){
int a=1, b=2;
cout << compute(a, b, &min) << endl;
cout << compute(a, b, &max) << endl;
cout << compute(a, b, &sum) << endl;
return 0;
}
动态分配
动态内存分配
int *p = new int[10];
delete[] p;
int *p = new Point(1,2);
delete p;
字符串
C风格字符串
char str[8] = "hello"; //以\0为结尾
char str[] = "hello";
string
#include <string>
string s = "hello";
s[0] = 'H';
s1+s2; // 字符串拼接
s.length()
对象指针
this指针
通过一个对象调用成员函数时,系统会将该对象的地址赋值给this指针,然后调用成员函数时隐含的使用了this指针
//定义
Point a(5, 10);
Point *ptr = &a;
//访问对象成员
ptr->getX(); //等价于(*ptr).getX();
//this指针
int Point::getX()
{
return x; //等价于return this->x;
}
智能指针
unique_ptr :不允许多个指针共享资源,可以使用move函数转移指针
shared_ptr:多个指针共享资源
weak_ptr:可以复制shared_ptr,但是其构造和释放对资源不产生影响
对象的复制与移动
深拷贝与浅拷贝
浅拷贝:对象成员的一一复制,当对象中含有指针时,会导致多个指针指向同一个资源
深拷贝:指针不指向同一份资源,会新建另外一份资源,然后将资源的值一一复制过来
移动构造函数
不进行复制,而是转移(C++11)
可以对临时对象(即将消亡)的资源直接移动,避免了多余的复制操作
#include<iostream>
using namespace std;
class IntNum {
public:
IntNum(int x = 0) : xptr(new int(x)){ //构造函数
cout << "Calling constructor..." << endl;
}
IntNum(const IntNum & n) : xptr(new int(*n.xptr)){//复制构造函数
cout << "Calling copy constructor..." << endl;
};
IntNum(IntNum && n): xptr( n.xptr){ //移动构造函数
n.xptr = nullptr;
cout << "Calling move constructor..." << endl;
}
~IntNum(){ //析构函数
delete xptr;
cout << "Destructing..." << endl;
}
int getInt() { return *xptr; }
private:
int *xptr;
};
IntNum getNum() {
IntNum a;
return a;
}
int main() {
cout << getNum().getInt() << endl;
return 0;
}