C++基础入门教程(六):为什么创建类的时候要用new?

今天是关于指针初步介绍的最后一篇,也是能让初学者明白为什么类是new出来的、为什么某些变量会莫名被释放,以及为什么木头会这么聪明。

1.使用new创建动态结构体

还记得我们的结构体吧?之前说过,结构体也是可以通过new来创建存储空间的,返回的是一个指向结构体类型空间的指针。

如下代码:

代码如下:

struct Man
    {
        int age;
        int IQ;
    };
    Man* pMan = new Man;
    pMan->IQ = 251;
    cout << pMan->IQ << "\n";
    cout << (*pMan).IQ << "\n";

定义一个结构体Man,然后使用new Man来动态创建内存空间,返回一个指针,这个指针指向一块用于存放Man类型的内存空间。
然后调用pMan->IQ给属性赋值,这里的“->”符号我们应该都很属性吧。
 
稍微说明一下,如果不是用new来创建的对象,那么,应该使用.符号来使用属性。
如果使用new创建的对象,则使用->符号来使用属性。
 
但实际上,最终还是.符号,->符号只是语法糖。
因为pMan是指针,所以*pMan是指针所指内存空间上的对象值,于是,调用属性是这样的:(*pMan).IQ
但每次都这么调用,很麻烦,于是就有了pMan->IQ这种方便的形式。
 
所以,大家不要再搞混了.和->了~
一般情况,可以理解为,指针都使用->符号。
 
(这段文字感觉解释地很糟糕,因为我旁边有人在一直说话,我思绪不太安静…)

2.为什么要有new?

为什么要有new?为什么要动态创建对象?为什么有时候不用new,有时候又用new,比如:

代码如下:

// Cocos2d-x3.x的Value类,大家都很熟悉了
Value v = Value(100);
// Cocos2d-x的Sprite类,也很属性了
Sprite* sp = new Sprite();

为什么有些地方不用new,有些地方又要new呢?
 
这就涉及到自动存储和动态存储了。

3.自动存储(自动变量、局部变量)

自动存储,也叫做自动变量,比如int num = 10; 这个num就属于自动变量。
所谓自动,代表它会自动申请内存,也会自动释放内存,自动变量是保存在栈里的(后进先出)。
 
如果大家觉得很难理解,那么,换一个名称——局部变量。
这个好理解了吧?局部变量在离开函数,或者离开它所属的代码块之后,就会被释放。
 
而Value v = Value(100); 、int num = 10; 这些都是局部变量,一旦离开函数或者离开它的作用域,就会被释放。
比如把int num; 作为成员变量,那么,在这个类被释放的时候,num变量也会被释放。
这就是为什么我们在创建了这么多int、float等基本类型的变量之后,不需要去释放它们。
因为它们是自动被释放的。

4.动态存储

自动变量有很大的好处,那就是不需要我们去管内存方面的事情,但是,有时候我们不希望有这样的自动释放内存。

我们希望自己去控制什么时候释放对象,这时候就要用到new了。

我们都知道,new了之后,如果不调用相应delete的话,申请到的内存空间是永远都不会被释放的。
这就是动态存储了,我们自己来申请内存,自己来释放内存。

当然,内存泄露的罪魁祸首之一也正是new~!

因为正常人都会有疏忽的时候,并且当程序足够庞大、逻辑足够复杂的时候,有些地方调用了new,却疏忽了delete是再正常不过了。
 
当然,new的作用也许不仅于此,书上目前还没深入介绍,我也不多说,免得说错,毕竟C++还是需要严谨一些的~

我不敢乱吹水~

5.vector和array

相信不少初学者会被Cocos2d-x3.x的Vector给弄迷糊了。

Vector是Cocos2d-x封装的一个类,而vector是C++里提供的一个类。

一个首字母大写,一个首字母小写,不要再弄错喇~
 
C++的vector是一种动态数组的实现,我们都知道,数组在声明的时候就要确定数组的大小,除非是使用new的方式。

vector就是使用new来申请内存的,但它已经封装好了,不需要我们去处理内存释放的问题。
 
vector的使用方式很简单:

代码如下:

// 可以在声明的时候就进行初始化
    vector<int> v = {1, 2};
    // 可以动态地添加新的元素进去
    v.push_back(5);
    // 使用at来获取某个元素
    cout << v.at(2);
    // 也可以像数组一样获取某个元素
    cout << v[2];

注意,使用vector要引入头文件:#include <vector>
既然是动态数组,那就肯定可以动态添加和删除元素。
获取元素的方式有两种,一种是使用at,这种方式比较安全,会检查下标是否合法。
也可以使用普通数组的方式来获取元素,这种方式比较危险,不会检查下标是否合法。
 
好了,vector就不多说了~
 
另外还有一个array类,这是C++11新增的。
vector是动态数组,效率自然要逊色一些。
而普通数组使用起来可能不太方便和安全。
于是,array诞生了,array也是固定长度的数组,但是使用起来可能更方便和安全:

代码如下:

array<int, 2> arr = { 1, 2 };
    cout << arr.at(1);

声明的方式比较特别,需要制定数组类型和大小,因为是固定长度的数组,大小也是不能变的。
获取元素的方式依旧有两种,使用at或者普通数组的方式,两种方式的区别和vector一样。

6.结束

好了,书籍第四章的内容到这里就结束了。
这一章的内存比较杂乱,算是什么知识都介绍了一些吧,但都不太深入。
最近事很多,希望能继续坚持。

(0)

相关推荐

  • C++模板类的用法实例

    本文实例讲述了C++中模板类的用法,分享给大家供大家参考.具体方法如下: //#include "StdAfx.h #ifndef __AFXTLS_H__ #define __AFXTLS_H__ #include <Windows.h> class CSimpleList { public: CSimpleList(int nNextOffset=0); void Construct(int nNextOffset); //接口 BOOL IsEmpty() const; voi

  • 一步一步学习PHP(5) 类和对象

    在这一节中,我们就来看看在PHP中如何创建一个类和对象. 1. 创建类 在PHP中,创建一个类和在C#/Java中基本类似,闲话少说,给大家看个最简单的例子: 复制代码 代码如下: <?php class People { var $name; public function GetName() { return $this->name; } public function SetName($name) { $this->name=$name; } } $p=new People();

  • C++对象的动态建立与释放详解

    =============下面先给出一个new和delete基本应用的例子,回顾一下它的基本用法============ 复制代码 代码如下: #include<iostream>using namespace std;int main(){ int *p;//定义一个指向int型变量的指针p  p=new int(3);//开辟一个存放整数的存储空间,返回一个指向该存储空间的的地址  cout<<*p<<endl; delete p;//释放该空间  char *p_

  • JavaScript定义类和对象的方法

    本文实例讲述了JavaScript定义类和对象的方法.分享给大家供大家参考.具体方法如下: 在JS中,类和对象有多种不同的写法,因为本人对JS也不怎么熟,所以就本人的理解来写,如果哪位朋友发现有不对,请告之,共同学习. JS定义一个类有两种定法(我只知道这两种): 1. 定义函数的方式: 定义: 复制代码 代码如下: function classA(a) {      this.aaa=a;  //添加一个属性      this.methodA=function(ppp)  //添加一个方法

  • C++类和对象实例解析(二)

    C++既是面向对象也是面向过程的语言,在这里就有一个重要的概念--类.         何谓类?类是对对象的一种抽象,举例来讲:每一个实实在在存在的人就是一个对象,人有很多共同的特征(一个头,两条腿,能走,能跑),这具有共同特征的人就成为一个类.类是一个抽象的名词,每一个人(即对象)是这个类的实例.         对象间具有的共同特征是对象的属性和行为.录像机是一个对象,它的属性是生产厂家.牌子.重量.颜色等等,它的行为就是它的功能,如录像.放像.快进.倒退等操作. C++程序中,需要先定义一

  • C++中对象的常引用总结

    直接传递对象名 用对象名做函数参数时,在函数调用时将建立一个新的对象,它是形参对象的拷贝. ================下面给出一个直接传递对象名的例子程序1.1================== 复制代码 代码如下: #include<iostream>using namespace std;class Time { public:  Time(int,int,int);//构造函数   void Print();//输出信息函数   void reset(Time t);//重置函数

  • C++中的string类的用法小结

    相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?答案是肯定的.也许有人会说,即使不用MFC框架,也可以想办法使用MFC中的API,具体的操作方法在本文最后给出操作方法.其实,可能很多人很可能会忽略掉标准C++中string类的使用.标准C++中提供的string类得功能也是非常强大的,一般都能满足我们开发项目时使用.现将具体用法的一部分罗列如下,只起一个

  • C++实现的链表类实例

    本文实例讲述了C++实现的链表类.分享给大家供大家参考.具体如下: #include <iostream> using namespace std; class linklist { private: struct node { int data; node *link; }*p; public: linklist(); void append( int num ); void add_as_first( int num ); void addafter( int c, int num );

  • JS创建类和对象的两种不同方式

    在JavaScript中, 当你定义了一个新的函数, 你实际上声明了一个新的类, 而这个函数本身就相当于类的构造函数.下面的代码向你展示了两种不同的方式来创建一个新的Person类, 而Person.prototype的定义也紧跟在函数定义之后. var Person = function(name) { // 一个匿名函数, 并将这个函数赋值给一个Person变量, 此时Person成为一个类 this.name = name; } function Person(name) { // 直接定

  • C++之类的静态变量

    成员变量 通过对象名能够访问public成员变量 每个对象都可以有只属于自己的成员变量 成员变量不能在对象之间共享 类的静态成员 静态成员变量 存储在 全局数据区 #include<stdio.h> class Test { private: ///静态成员变量访问权限 static int c1; public: static int GetC1() { return c1; } static void SetC1(int i) { c1=i; } void print() //普通成员函数

  • Javascript学习笔记5 类和对象

    面向对象语言三大特点:继承,多态,封装,这三点虽然Javascript没有提供天然的语法实现,但是我们都可以通过prototype等技巧来实现,因此这种说法似乎不过分. 在Javascript中,构造对象有三种方式: 1. 首先,我们要明确一个概念,Javascript是一种弱类型的语言,一方面体现在Javascript的变量,返回类型都是没有强类型约束的,另一方面,Javascript可以为对象任意添加属性和方法.根据这个,我们可以写出这样的代码: 复制代码 代码如下: <script typ

  • C++中对象的赋值与复制操作详细解析

    对象的赋值 如果对一个类定义了两个或多个对象,则这些同类的对象之间可以互相赋值,或者说,一个对象的值可以赋给另一个同类的对象.这里所指的对象的值是指对象中所有数据成员的值. 对象之间的赋值也是通过赋值运算符"="进行的.本来赋值运算符"="只能用来对单个的变量赋值,现在被扩展为两个同类对象之间的赋值,这是通过对赋值运算符的重载实现的. 实际上这个过程是通过成员复制来实现的,即将一个对象的成员值一一复制给另外一个对象的成员.对象赋值的一般形式: 对象名1=对象名2;

  • C++中的对象指针总结

    指向对象的指针在建立对象的时候,变异系统会给每一个对象分配一定的存储空间,以存放其成员.对象空间的起始地址就是对象的指针.可以定义一个指针变量,用来存放对象的指针. 一个简单的示例1.1: 复制代码 代码如下: #include<iostream>using namespace std;class Student{ public:  int num;  int score;  Student(int ,int );//声明构造函数  void Print();//声明输出信息函数};Stude

  • C++封装线程类的实现方法

    本文实例讲述了C++封装线程类的实现方法.分享给大家供大家参考.具体方法如下: 复制代码 代码如下: // 给主窗口的通知消息  #define WM_CUTTERSTART WM_USER + 100    // wParam == xxx  lParam==xxxx    /*  外面调用这个类时,只需要IsRunning() Startxxx(xxx) Suspendxxx()   Resumexxx() Stopxxx()  */    /*  m_bContinue在真正的工作代码Do

随机推荐