创建对象有以下四种形式:

#include <iostream>
using namespace std; class A{
private:
int i;
public:
A(){ cout<<"调用没有参数的构造函数"<<endl; }
A(int a):i(a){ cout<<"调用有一个参数的构造函数"<<endl; }
~A(){cout<<"成员变量为:"<<i<<"\t调用析构函数"<<endl;}
}; void main(){
A a0; //形式一:直接声明一个对象
A a1(1); //形式二:隐式调用A带一个参数的构造函数
A a2 = A(2); //形式三:显式调用A带一个参数构造函数
A *p = new A(3); //形式四:动态分配
}

形式一:实际上等同于  A  a0 = A();调用不带参数的构造函数进行对象的创建

形式二:实际上等同于  A  a1 = A(1);调用带一个参数的构造函数进行对象的创建
形式三:与形式二相同,这三种形式其实都是按照参数调用对应的构造函数在栈中创建对象,使用完毕后,系统自动回收对象内存,无需手动释放。

形式四:在堆内存中动态开辟空间创建对象,需要手动释放内存。
还有一点需要注意“A a3();”编译和运行都没有问题,但是并没有创建对象
运行结果:


由图可以得出如下结果:
(1)创建对象需要调用对应的构造函数,释放对象需要调用析构函数。因为形式一对应的构造函数没有对对象进行初始化所以成员变量i出现随机数“-858993460”.
(2)析构的顺序与构造顺序相反,上面代码中构造顺序是a0,a1,a2 ;析构顺序是a2,a1,a0.
(3)在栈中创建的对象无需手动释放,系统自动回收。在堆中创建的对象需要手动释放。在运行结果中调用了4次构造函数,然而析构函数只执行了3次,没有释放指针p所指向的对象。在上面程序末尾加入代码delete p;p=NULL;运行结果如下:

堆中的对象也被删除了。
但需要注意的是delete p;只是释放了内存空间,指针p仍然指向那块空间,所以一定要将p指针置为NULL;
#include <iostream>
using namespace std; class A{
private:
int i;
public:
A(){ cout<<"调用没有参数的构造函数"<<endl; }
A(int a):i(a){ cout<<"调用有一个参数的构造函数"<<endl; }
~A(){cout<<"成员变量为:"<<i<<"\t调用析构函数"<<endl;}
}; void main(){
A a0; //方法一:直接声明一个对象
A a1(1); //方法二:隐式调用A带一个参数的构造函数
A a2 = A(2); //方法三:显式调用A带一个参数构造函数
A *p = new A(3); //方法四:动态分配
delete p;
cout<<"delete后指针p指向的空间:"<<p<<endl;
p=NULL;
}

运行结果如下:




还需要注意的一点是,delete不能释放栈中的空间。我曾经犯过一个错误,错误代码如下:
#include <iostream>
using namespace std; class A{
private:
int i;
public:
A(){ cout<<"调用没有参数的构造函数"<<endl; }
A(int a):i(a){ cout<<"调用有一个参数的构造函数"<<endl; }
~A(){cout<<"成员变量为:"<<i<<"\t调用析构函数"<<endl;}
}; void main(){
A a(1);
A *p1 = &a;
delete p1; //希望释放栈中的对象
}

编译没有问题,但运行出错。

所以delete一定要和new成对出现,delete释放的是动态开辟的内存。栈中的内存不需要咱们去释放,系统自己会回收。


如果构造函数有默认参数,则可能出现不知道调用哪个构造函数的问题
#include <iostream>
using namespace std; class A{
private:
int i;
public:
A(){cout<<"调用没有参数的构造函数"<<endl;}
A(int a = 0):i(a){ cout<<"调用有一个参数的构造函数"<<endl; }
}; void main(){
A a0;
}

编译器不知道该调用哪一个构造函数,所以删除其中一个构造函数即可。

C++对象创建与释放的更多相关文章

  1. .NET Core 对象( Transient、Scope、Singleton )生命周期详解 (对象创建以及释放)

    首先我们在VS2019中创建一个.NET Core的控制台程序,方便演示: 需要安装两个依赖包 Microsoft.Extensions.DependencyInjection 依赖注入对象的具体实现 ...

  2. 不可或缺 Windows Native (19) - C++: 对象的动态创建和释放, 对象的赋值和复制, 静态属性和静态函数, 类模板

    [源码下载] 不可或缺 Windows Native (19) - C++: 对象的动态创建和释放, 对象的赋值和复制, 静态属性和静态函数, 类模板 作者:webabcd 介绍不可或缺 Window ...

  3. C++中new和delete来创建和释放动态数组

    在C++编程中,使用new创建数组然后用delete来释放. 一.创建并释放一维数组 #include<iostream> using namespace std; int main() ...

  4. 关于Java String对象创建的几点疑问

    我们通过JDK源码会知道String实质是字符数组,而且是不可被继承(final)和具有不可变性(immutable).可以如果想要了解String的创建我们需要先了解下JVM的内存结构. 1.JVM ...

  5. 关于String的对象创建

    1)String String是Java中的字符串类,属于引用数据类型.所以String的对象存放的是引用的地址.在底层是一个字符型数组. String是不可变的.所谓的不可变是指一个对象有了一个引用 ...

  6. OC对象,自动释放池,OC与C语言的区别

    在C语言中,编程都是面向过程的编程,每一个代码块都严格按照从上至下的顺序执行,在代码块之间同样也是这样, 但是在OC中往往不是这样,OC和C++.java等语言一样,都是面向对象的编程语言,在代码的执 ...

  7. [你必须知道的.NET]第十九回:对象创建始末(下)

    本文将介绍以下内容: 对象的创建过程 内存分配分析 内存布局研究 接上回[第十八回:对象创建始末(上)],继续对对象创建话题的讨论>>> 2.2 托管堆的内存分配机制 引用类型的实例 ...

  8. [你必须知道的.NET]第十八回:对象创建始末(上)

    本文将介绍以下内容: 对象的创建过程 内存分配分析 内存布局研究 1. 引言 了解.NET的内存管理机制,首先应该从内存分配开始,也就是对象的创建环节.对象的创建,是个复杂的过程,主要包括内存分配和初 ...

  9. 使用C++为对象分配与释放内存时的几个好习惯

    本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cnblogs.com/dbylk/ 最近在为公司的项目写内存泄漏定位工具,遇到一些关于C++构造与析构对象的问题,在此记录一下 ...

随机推荐

  1. 有关AES加密的问题

    遇到一个项目,需要用AES加密密码,android的已经写好了,java源码: private static final String AES_OPTIONS = "AES/ECB/PKCS ...

  2. FindWindow使用方法

    函数功能:该函数获得一个顶层窗体的句柄,该窗体的类名和窗体名与给定的字符串相匹配.这个函数不查找子窗体.在查找时不区分大写和小写. 函数型:HWND FindWindow(LPCTSTR IpClas ...

  3. Centos中安装vim

    Centos, 默认没有安装VIM, 所以要当然要安装了, 直接yum install vim是不行的, 首先: yum install vim* 会看到vim-enhanced这个包,没错, 我们要 ...

  4. OpenCV快速遍历矩阵元素方法

    OpenCV中Mat矩阵data数据的存储方式和二维数组不一致,二维数组按照行优先的顺序依次存储,而Mat中还有一个标示行步进的变量Step.使用Mat.ptr<DataTyte>(row ...

  5. STL之Map的运用

    Map是c++的一个标准容器,她提供了非常好一对一的关系,在一些程序中建立一个map能够起到事半功倍的效果,总结了一些map基本简单有用的操作! 1. map最主要的构造函数:    map<s ...

  6. android.annotation cannot be resolved

    http://stackoverflow.com/questions/14870596/android-annotation-cannot-be-resolved As Artem suggested ...

  7. 详解Android Handler的使用

    我们进行Android开发时,Handler可以说是使用非常频繁的一个概念,它的用处不言而喻.本文就详细介绍Handler的基本概念和用法. Handler的基本概念         Handler主 ...

  8. iOS开发——面试笔试精华(四)

    面试笔试精华(四) 1.        Object-C有多继承吗?没有的话用什么代替?
 1>  OC是单继承,没有多继承 2>  有时可以用分类和协议来代替多继承 2.        ...

  9. 在Struts2中使用ValueStack、ActionContext、ServletContext、request、session等 .

    笔者不知道该用哪个词来形容ValueStack.ActionContext等可以在Struts2中用来存放数据的类.这些类使用的范围不同,得到的方法也不同,下面就来一一介绍. 声明:本文参考Strut ...

  10. linux中的工具

    远程连接linux的工具: 命令行: SecureCRT   putty  XShell(商业环境付费) 图形界面:WinSCP SecureFX 远程连接window服务器工具: FileZilla ...