【和春笋一起学C++】(五十三)使用指向对象的指针

目录

[1 指向对象的指针使用示例](#1 指向对象的指针使用示例)

[2 小结](#2 小结)


1 指向对象的指针使用示例

使用《C++中string类的简介》文章中声明的MyClassString类,定义一个MyClassString类对象的数组,找出数组中字符串长度最大的MyClassString对象,这里使用一个指向MyClassString类对象的指针来跟踪数组中长度最长的字符串,代码如下:

cpp 复制代码
////方法一
int main()
{
	using namespace std;
	MyClassString ar_st[] = { "rice","food","cat","home","school","cake","dog" };
	size_t length = sizeof(ar_st) / sizeof(ar_st[0]);
	MyClassString *st = &ar_st[0];
	for (int i = 0; i < length; i++)
	{
		if (ar_st[i].length() > st->length())
		{
			st = &ar_st[i];
		}
	}
	cout << "max length string: " << *st << ",  length is " << st->length() << endl;
	return 0;
}

程序说明:程序定义一个指向MyClassString类对象的指针,并将它指向数组中第一个元素的地址,通过for循环逐个比较数组中字符串长度,找出长度最大的字符串,因st为指向MyClassString对象的指针,因此可以使用->操作符访问类方法。

方法二:还可以使用new操作符来定义一个指向MyClassString对象的指针。

cpp 复制代码
///方法二
int main()
{
	using namespace std;
	MyClassString ar_st[] = { "rice","food","cat","home","school","cake","dog" };
	size_t length = sizeof(ar_st) / sizeof(ar_st[0]);
    MyClassString *st = new MyClassString;
	for (int i = 0; i < length; i++)
	{
		if (ar_st[i].length() > st->length())
		{
			st = &ar_st[i];
		}
	}
	cout << "max length string: " << *st << ",  length is " << st->length() << endl;
	return 0;
}

程序说明:上面代码中虽然使用了new操作符,但不能使用delete来释放st所指向的内存空间,原因如下:

cpp 复制代码
MyClassString *st = new MyClassString;

该语句的含义是使用默认构造函数创建一个未被命名的对象,并使st指向该对象

在for循环语句中st由指向未被命名的对象变成指向ar_st数组中的某一个元素,如果再使用delete释放st所指向的内存空间,将引发错误,因为此时st指向了ar_st数组中的某一个元素,**而ar_st数组中的元素存放在栈上,使用delete释放栈上的内存空间则必然导致程序运行崩溃。**所以在该程序中的for循环之后不能使用delete释放st所指向的内存空间。

在该程序中还可以将语句MyClassString *st = new MyClassString;换成如下语句:

cpp 复制代码
MyClassString *st = new MyClassString(ar_st[0]);

上面语句表示使用构造函数MyClassString(const MyClassString& st)来创建一个未被命名的对象,并使st指向该对象。此处的new分配的内存空间是用来存储对象的,用来保存str指针的地址以及len成员,并不会保存str所指向的字符串。而创建一个未被命名的对象时,将调用构造函数,构造函数将使用new分配用于存储字符串的内存空间,并将字符串的地址赋给str。同样,当使用delete释放st时,释放的是存储str指针地址和len成员的空间,并不释放str指向的内存空间,而该任务将由对象的析构函数来完成。

析构函数在下面几种情况下都会被调用:

  • 如果对象是动态变量,则当执行完定义该对象的程序块时,将调用该对象的析构函数;
  • 如果对象是静态变量,则在程序结束时将调用对象的析构函数。
  • 如果对象是用new创建的,则仅当显式使用delete删除对象时,其析构函数才会被调用;

所以方法二会造成内存泄露,未被命名的对象所占据的内存空间没有被释放,同样也没有调用该对象的析构函数。

2 小结

以《C++中string类的简介》文章中声明的MyClassString类为例:

  1. 使用常规表示法来声明指向对象的指针:
cpp 复制代码
MyClassString *st;
  1. 将指针初始化为指向已有的对象。示例程序中方法一使用的方式:
cpp 复制代码
MyClassString *st = &ar_st[0];
  1. 使用new来初始化指针,这将创建一个新的对象,示例程序中方法二使用的方式:
cpp 复制代码
MyClassString *st = new MyClassString(ar_st[0]);

注:对类使用new将调用相应的类构造函数来初始化新创建的对象。

cpp 复制代码
///调用默认构造函数创建新对象
MyClassString *st = new MyClassString;
////调用复制构造函数创建新对象:MyClassString(const MyClassString& st);
MyClassString *st = new MyClassString(ar_st[0]);
////调用该构造函数创建新对象:MyClassString(const char* s);
MyClassString *st = new MyClassString("school");
  1. 指向对象的指针可以通过->操作符访问类方法,如示例代码中的st访问类的length方法:
cpp 复制代码
cout << "max length string: " << *st << ",  length is " << st->length() << endl;
  1. 可以对指向对象的指针应用解除引用操作符来获得对象,如示例代码中对st应用解除引用操作符:
cpp 复制代码
cout << "max length string: " << *st << ",  length is " << st->length() << endl;
相关推荐
迷途之人不知返5 分钟前
深入讨论模板
c++
AI进化营-智能译站15 分钟前
ROS2 C++开发系列18-STL容器实战:deque缓存激光雷达数据|priority_queue调度任务
开发语言·c++·缓存·ai
hehelm29 分钟前
C++11 新特性
c++
我不是懒洋洋32 分钟前
【数据结构】排序算法(直接插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序、归并排序、计数排序)
c语言·数据结构·c++·经验分享·算法·排序算法
邪修king34 分钟前
UE5:C++ 实现 游戏逻辑 ↔ UI 双向联动
c++·游戏·ue5
汉克老师10 小时前
GESP2025年3月认证C++五级( 第三部分编程题(1、平均分配))
c++·算法·贪心算法·排序·gesp5级·gesp五级
智者知已应修善业13 小时前
【51单片机2个按键控制流水灯运行与暂停】2023-9-6
c++·经验分享·笔记·算法·51单片机
云泽80815 小时前
C++11 核心特性全解:列表初始化、右值引用与移动语义实战
开发语言·c++
AI进化营-智能译站16 小时前
ROS2 C++开发系列12-用多态与虚函数构建可扩展的ROS2机器人行为模块
开发语言·c++·ai·机器人
Morwit16 小时前
QML组件之间的通信方案(暴露子组件)
c++·qt·职场和发展