C++程序设计数组、指针、字符串
以指针作为函数参数
为什么需要用指针做参数?
- 需要数据双向传递时(引用也可以达到此效果)
- 用指针作为函数的参数,可以使被调函数通过形参指针存取主调函数中实参指针指向的数据,实现数据的双向传递
- 需要传递一组数据,只传首地址运行效率比较高
- 实参是数组名时形参可以是指针
指针类型的函数
若函数的返回值是指针,该函数就是指针类型的函数。
指针函数的定义形式
存储类型 数据类型 *函数名() { //函数体语句 }
注意
- 不要将非静态局部地址用作函数的返回值
- 错误的例子:在子函数中定义局部变量后将其地址返回给主函数,就是非法地址
- 返回的指针要确保在主调函数中是有效、合法的地址
- 正确的例子:
主函数中定义的数组,在子函数中对该数组元素进行某种操作后,返回其中一个元素的地址,这就是合法有效的地址
- 返回的指针要确保在主调函数中是有效、合法的地址
- 正确的例子:
在子函数中通过动态内存分配new操作取得的内存地址返回给主函数是合法有效的,但是内存分配和释放不在同一级别,要注意不能忘记释放,避免内存泄漏
错误的例子
int main(){
int* function();
int* ptr= function();
*prt=5; //危险的访问!
return 0;
}
int* function(){
int local=0; //非静态局部变量作用域和寿命都仅限于本函数体内
return &local;
}//函数运行结束时,变量local被释
函数指针的定义
定义形式:存储类型 数据类型 (*函数指针名)();
含义: 函数指针指向的是程序代码存储区。
作用:将函数的指针作为参数传递给一个函数,使得在处理相似问题的时候可以灵活的使用不同的方法。
动态内存分配
动态申请内存操作符 new
-
new 类型名T(初始化参数列表)
-
功能:在程序执行期间,申请用于存放T类型对象的内存空间,并依初值列表赋以初值。
-
结果值:成功:T类型的指针,指向新分配的内存;失败:抛出异常。
释放内存操作符delete
-
delete 指针p
-
功能:释放指针p所指向的内存。p必须是new操作的返回值。
分配和释放动态数组
-
分配:new 类型名T [ 数组长度 ]
-
数组长度可以是任何表达式,在运行时计算
-
-
释放:delete[] 数组名p
-
释放指针p所指向的数组。
p必须是用new分配得到的数组首地址。
-
C++11的智能指针
-
unique_ptr :不允许多个指针共享资源,可以用标准库中的move函数转移指针
-
shared_ptr :多个指针共享资源
-
weak_ptr :可复制shared_ptr,但其构造或者释放对资源不产生影响
浅层复制与深层复制
-
浅层复制
-
实现对象间数据元素的一一对应复制。
-
class ArrayOfPoints { public: ArrayOfPoints(const ArrayOfPoints& pointsArray); //其他成员同例6-18 }; ArrayOfPoints::ArrayOfPoints(const ArrayOfPoints& v) { size = v.size; points = new Point[size]; for (int i = 0; i < size; i++) points[i] = v.points[i]; }
-
-
-
深层复制
-
当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指对象进行复制。
-
移动构造
-
当临时对象在被复制后,就不再被利用了。我们完全可以把临时对象的资源直接移动,这样就避免了多余的复制操作。
移动构造
-
什么时候该触发移动构造?
-
有可被利用的临时对象
-
-
移动构造函数:
class_name ( class_name && )
•&&是右值引用
•函数返回的临时变量是右值
IntNum(IntNum && n): xptr( n.xptr){ //移动构造函数
n.xptr = nullptr;
cout << "Calling move constructor..." << endl;
}