当前位置:首页 > 芯闻号 > 充电吧
[导读]我最不喜欢循规循矩,虽然是让写笔记,照着老师的ppt抄一遍有什么意思。所以我还是喜欢写自己的东西。最近我有个怪癖,爱把所有带指针的类都改造成使用智能指针来控制资源分配和回收。因为我认为既然是c++11

我最不喜欢循规循矩,虽然是让写笔记,照着老师的ppt抄一遍有什么意思。所以我还是喜欢写自己的东西。

最近我有个怪癖,爱把所有带指针的类都改造成使用智能指针来控制资源分配和回收。因为我认为既然是c++11标准出的应该是可以顶替99标准,更安全更先进的用法,为什么不用呢?结果在这两周侯捷老师的c++课上的例子的智能指针改写上吃了苦头,也领悟到什么时候该用智能指针,什么时候不该用。离提交作业的日期只剩两天不到,有空的话我会将我对Date类,Rectangle类的改写也在这里讲一下。

我这里目的并不是讲解智能指针,所以讲的并不细。

什么是智能指针:

智能指针就是通过模板实现的对普通指针的一种封装,我偏爱用shared_ptr指针。通过引用计数,来管理自己的引用数量,当计数为0时,自动释放内存。

什么时候该用它呢?

本来我有个A类型的指针:

A *a = new A();

这样我还要操心去delete它。假如这行代码在一个函数内,并且a会作为该函数的返回值返回的话(比如第一周的作业Date类随机产生10个日期返回的函数)那选择什么时候delete就很重要了。有的时候不好抉择,增加维护的复杂程度。

那么这就是智能指针大显身手的时候。

shared_ptr a = make_shared();

起到了和刚才那条语句一样的效果。
假如这个函数是

shared_ptr fun() {
  shared_ptr a = make_shared();
// 对a做点什么
 return a;
}

这样的话,函数里定义a,引用计数为1,返回a,a的引用计数仍为1.而当a使用完毕后,到了函数使用时所在作用域的结束位置时。a的引用计数会-1,此时为0,自动释放内存。不用我们人工delete了。

String类不使用shared的模样

这个String类是我自己写的,但跟课程里的只有一点点不一样。
返回成员的函数返回类型我设为const char*,因为这样的话可以避免使用函数时对成员做出我们不期望的修改。

#ifndef STRING_H
#define STRING_H

#include#includeusing std::ostream;

class String {
public:
    String(const char *cstr = 0);
    String(const String&);
    String &operator=(const String&);
    ~String();
    const char* get() const;
private:
    char *m_data;
};

inline
String::String(const char *cstr) {
    if (cstr) {
        m_data = new char[strlen(cstr) + 1];
        strcpy(m_data, cstr);
    } else {
        m_data = new char[1];
        *m_data = '';
    }
}

inline
String::String(const String &str) {
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);
}

inline
String& String::operator=(const String &right) {
    if (this == &right) return *this;

    delete[] m_data;
    m_data = new char[strlen(right.m_data) + 1];
    strcpy(m_data, right.m_data);

    return *this;
}

inline
String::~String() {
    delete[] m_data;
}

inline
const char* String::get() const {  // 这里返回类型加了const
    return m_data;
}

inline
ostream& operator<<(ostream& os, const String& str) {
    // auto s = str.get();
    // strcpy(s, "h");
    return os << str.get();
}
#endif

这是使用后(惨不忍睹,跑不起来):

#ifndef STRING_H
#define STRING_H

#include#include#includeusing std::ostream;
using std::shared_ptr;
using std::make_shared;

class String {
public:
    String(const char *cstr = 0);
    String(const String&);
    String &operator=(const String&);
    ~String();
    const char* get() const;
private:
    shared_ptrm_data;
};

inline
String::String(const char *cstr) {
    char* pstr; 
    if (cstr) {
        pstr = new char[strlen(cstr) + 1];
        strcpy(pstr, cstr);
    } else {
        pstr = new char[1];
        pstr = '';
    }
    m_data = make_shared(pstr, [](char *pstr){ delete[] pstr; });
}

inline
const char* String::get() const {
    return m_data.get();
}

inline
ostream& operator<<(ostream& os, const String& str) {
    return os << str.get();
}
#endif

这里可以明确的告诉大家,这段程序跑不起啦。但是这里可以看出智能指针的一个优点。那就是使用智能指针后,所有成员都不是指针类型,若没有特殊操作的话,拷贝构造,赋值运算符重载,析构,三大函数都可以只用默认的就可以,极大的减少了代码量。

但这个类并不适宜用智能指针。原因现在可能看不太出来。接下来我会将我对Date类的改写和Rectangle类的改写放出来。这样就比较清晰了。

Date类同理,也跑不起来,但我还是在这里把代码贴上

/*
 * 用于随机生成和排序的数组
 */
const int DATE_SIZE = 10;
/*
 * 生成10个随机日期
 */
unique_ptrCreatePoints() {
    unique_ptrdates(new Date[DATE_SIZE]);
    for (int i = 0; i < DATE_SIZE; ++i) {
        int year = rand() % 1000 + 1500;
        int month = rand() % 12 + 1;
 
        int maxDay = 28;
        switch (month) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                maxDay = 31;
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                maxDay = 30;
                break;
            case 2:
                if ((year % 4 == 0 && year % 100 != 0)
                        || year % 400 == 0) 
                    maxDay = 29;
                break;
        }
        int day = rand() % maxDay + 1;
 
        dates[i] = Date(year, month, day);
    }
 
    return dates;
}
 
/*
 *    按从小到大的顺序排列日期数组
 */
unique_ptrSort(unique_ptr&dates) {
    sort(&dates[0], &(dates[DATE_SIZE - 1]) + 1);
    return dates;
}

这两者的共同点就是需要改造成智能指针的都是数组,也就是说,如果数组之类对要绑定成智能指针的变量有依赖或顺序关系的情形下,使用智能指针并不明智,c++ primer书中也讲,尽量少用数组,多用标准库容器。而不得不用数组的情况下,还是使用new,delete管理或别的方式比较好。

而有的情形很适合智能指针,比如下面的Rectangle类:

class Shape {
    int no;
};

class Point {
    int x, y;
public:
    Point() = default;
    Point(const int &x = 0, const int &y = 0):x(x), y(y){}
};

class Rectangle: public Shape {
    int width, height;
    shared_ptrleftUp;
public:
    Rectangle(const int&, const int&, const int&, const int&);
    // 使用智能指针,拷贝,赋值,析构使用默认即可
};

inline
Rectangle::Rectangle(const int &w, const int &h, const int &x, const int &y):leftUp(make_shared(x, y)), width(w), height(h){}

这样成员只是单个对象的时候将其改为智能指针就很爽啦,Rectangle类的拷贝,赋值,析构全部省去,也不用有释放内存问题的担心。

这只是我这几天学习c++以来的想法,不一定正确,等以后功力深了说不定我自己都会推翻现在的想法。所以有什么疑问尽管在下面留言,希望我们的思想能碰撞出智慧的火光,共同进步。



作者:T4Technology

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

对象类 一个类定义了一组对象。类具有行为(be-havoir),它描述一个对象能够做什么以及做的方法(method),它们是可以对这个对象进行操作的程序和过程。

关键字: 对象 行为

今天跟大家聊一下 BAT 面试 C++ 开发工程师必问的一个考点:智能指针。

关键字: C 智能指针

c++程序员面试过程中基本上都会被问到c++11新特性吧,你是怎么回答的呢? 本文基本上涵盖了c++11的所有新特性,并有详细代码介绍其用法,对关键知识点做了深入分析,对重要的知识点我单独写了相关文章并附上了相关链接,我...

关键字: c++11

很多人谈到c++,说它特别难,可能有一部分就是因为c++的内存管理吧,不像java那样有虚拟机动态的管理内存,在程序运行过程中可能就会出现内存泄漏,然而这种问题其实都可以通过c++11引入的智能指针来解决,相反我还认为这...

关键字: c++11

c++11关于并发引入了好多好东西,这里按照如下顺序介绍: std::thread相关 std::mutex相关 std::lock相关 std::atomic相关 std::call_once相关 volatile相关...

关键字: 线程 c++11

12月7日 据报道,今天正在带来形形色色的突破,从而促进诸如疾病诊断、粮食生产以及人们相互交谈的方式等用途。想象一下50年后令人着迷的东西,位于列表顶端的将是什么?

关键字: AI 水藻

以前,在lambda表达式没有进入标准的时候,对容器的遍历等涉及到使用函数指针的情况,一般人会懒得使用std::for_each,或std::transform,也许只是一个短短的几句话,却要单独写个

关键字: c++ c++11

在UML类图中,常见的有以下几种关系:泛化(Generalization),  实现(Realization),关联(Association),聚合(Aggregation),组合(Compositi

关键字: uml

C++11终于知道要在语言中加入匿名函数了。匿名函数在很多时候可以为编码提供便利,这在下文会提到。很多语言中的匿名函数,如C++,都是用Lambda表达式实现的。Lambda表达式又称为lambda函

关键字: c++11 lambda函数

正文         智能指针能够使C++的开发简单化,主要是它能够像其它限制性语言(如C#、VB)自动管理内存的释放,而且能够做更多的事情。1、 什么是智能指针智能指针是一种像指针的C++对象,但它

关键字: 智能指针 c++.boost
关闭
关闭