C++类实例化与智能指针

声明:本文参考了references中列的文章,并加以整理总结。
指针的值是对象的地址,指针可以看做一个存放地址值的整型。

类实例化

  1. 类实例化的两种方式
#include<iostream>
#include<cstring>
#include<string>
using namespace std;

class C {
public:
    C(string s = "", int i = 0, double d = 1.0) {
        dataMember1 = s;
        dataMember2 = i;
        dataMember3 = d;
    }
    void memberFunction1() {
        cout << dataMember1 <<' '<<dataMember2 <<' ' << dataMember3 << endl;
    }
    void memberFunction2(int i, string s1 = "unknow") {
        dataMember2 = i;
        cout << i << " received from " << s1 <<endl;
    }
protected:
    string dataMember1;
    int dataMember2;
    double dataMember3;
};
int main() {
    //创建类实例方法1:直接声明并调用构造函数
    C obj1("o1", 11, 111);
    obj1.memberFunction1();

    //创建类实例方法2:使用指针创建,程序运行完毕后必须释放内存
    C *obj2 = new C("O2", 22, 222.0);
    obj2->memberFunction1();
    obj2->memberFunction2(1000, "C++");
    delete obj2;

    cout << "The end!" << endl;
    return 0;
}
  1. 创建类对象new与不new的区别
    下面是自己总结的一些关于new创建类对象特点:
    new创建类对象需要指针接收,一处初始化,多处使用
    new创建类对象使用完需delete销毁
    new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间
    new对象指针用途广泛,比如作为函数返回值、函数参数等
    频繁调用场合并不适合new,就像new申请和释放内存一样。
Student  student(20) ;  
//这里student是引用 对象分配在 栈空间中,这里只是我的理解

Student *student = new  Student(20);  
//这里student是指针,new Student(20)是分配在堆内存空间的
  1. new对象指针作为函数参数和返回值
class CTest {  public:   int a;  };    
class CBest {  public:   int b;  };    
CTest* fun(CBest* pBest) {  
	CTest* pTest = new CTest();   
	pTest->a = pBest->b;
	return pTest;  
}    
int main() {  
    CBest* pBest = new CBest();   
    CTest* pRes= fun(pBest);      
    if(pBest!=NULL)    
    delete pBest;   
    if(pRes!=NULL)    
    delete pRes ;   
    return 0;  
}
  1. 必看 (讲了函数参数和多态)
    https://www.jianshu.com/p/a75b267325c2

智能指针

https://blog.csdn.net/weixin_42205987/article/details/82946894

#include <memory>  //智能指针所在头文件

shared_ptr 是模板类,所以在创建 shared_ptr 时需要指定其指向的类型。shared_ptr 负责在不使用实例时自动释放由它管理的对象,同时它可以自由的共享它指向的对象。
std::shared_ptr大概总结有以下几点:
(1) 智能指针主要的用途就是方便资源的管理,自动释放没有指针引用的资源。
(2) 使用引用计数来标识是否有多余指针指向该资源。(注意,shart_ptr本身指针会占1个引用)。
(3) 在赋值操作中, 原来资源的引用计数会减一,新指向的资源引用计数会加一。

 std::shared_ptr<Test> p1(new Test);
 std::shared_ptr<Test> p2(new Test);
 p1 = p2;

(4) 引用计数加一/减一操作是原子操作,所以线程安全的。
(5) make_shared要优于使用new,make_shared可以一次将需要内存分配好。

// Test 是一个class
std::shared_ptr<Test> p = std::make_shared<Test>(); //推荐
std::shared_ptr<Test> p(new Test);
//std::shared_ptr<Test> p = new Test(); //错误写法!

(6) std::shared_ptr的大小是原始指针的两倍,因为它的内部有一个原始指针指向资源,同时有个指针指向引用计数。
(7) 引用计数是分配在动态分配的,std::shared_ptr支持拷贝,新的指针获可以获取前引用计数个数。

#include <iostream>
#include <string>
#include <memory>
using namespace std;
class Test
{
public:
    Test(string name = "initial") //构造函数 initial是默认值
    {
        this->name_ = name;
        cout << this->name_ << "  constructor" << endl;
    }
    ~Test() //析构函数
    {
        cout << this->name_ << "  destructor" << endl;
    }

    string name_; //data member
};
int main()
{
    /* 类对象 原生指针构造 */
    shared_ptr<Test> pStr1 = make_shared<Test>("BUAA");
//    shared_ptr<Test> pStr1(new Test("BUAA")); //another method
    cout << (*pStr1).name_ << endl;
    cout << pStr1->name_ << endl;

    /* use_count()检查引用计数 */
    cout << "pStr1 引用计数:" << pStr1.use_count() << endl;

    shared_ptr<Test> pStr2 = pStr1;
    cout << (*pStr2).name_ << endl;
    cout << "pStr1 引用计数:" << pStr1.use_count() << endl;
    cout << "pStr2 引用计数:" << pStr2.use_count() << endl;

    /* 先new 一个对象,把原始指针传递给shared_ptr的构造函数 */
    int *pInt1 = new int(11);
    shared_ptr<int> pInt2(pInt1);

    /* unique()来检查某个shared_ptr 是否是原始指针唯一拥有者 */
    cout << "pInt2.unique() is " << pInt2.unique() << endl; //true 1
    /* 用一个shared_ptr对象来初始化另一个shared_ptr实例 */
    shared_ptr<int> pInt3(pInt2);
    cout << "pInt2.unique() is " << pInt2.unique() << endl; //false 0

    cout << "pInt3 引用计数:" << pInt3.use_count() << endl;
    cout << "pInt2 引用计数:" << pInt2.use_count() << endl;
    return 0;
}

output :
在这里插入图片描述

STL容器中存指针,如何delete

必看:https://blog.csdn.net/AC_huang/article/details/29382629
STL中不管是erase或remove都不会释放对象的内存空间,他只是释放了STL里面用来存放这个对象或指针的空间,所以依然需要自己去手动释放,并且释放是有先后顺序的,要先delete 再调用STL里容器对应的erase函数。

vector<Data *> san_dian;
vector<Data *>::iterator it;
for(it = san_dian.begin(); it != san_dian.end(); ) {
    delete *it;
    it = san_dian.erase(it);
}

references

https://blog.csdn.net/u010039733/article/details/51926966
https://blog.csdn.net/tham_/article/details/44906571
堆空间与栈空间的区别
https://blog.csdn.net/Mormont/article/details/53511441
智能指针
https://blog.csdn.net/weixin_42205987/article/details/82946894
https://blog.csdn.net/thinkerleo1997/article/details/78754919

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值