4

Effective C++(第三版)第三章笔记

 2 years ago
source link: https://xusiwei.github.io/post/2020/04/effective-cpp-notes3/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

13. 以对象管理资源

  • RAII(Resource Acquisition Is Initialization),通俗的说就是用类的构造函数和和析构函数管理资源。
  • C++98 有 auto_ptr (C++17中被废弃,不再能够使用)
  • C++11 有 unique_ptr (用于取代auto_ptr),shared_ptr 、weak_ptr (用于避免 shared_ptr 的循环引用)

14. 资源管理类中小心copying行为

表示不同资源的RAII类,对于拷贝行为的需求也不同:

  • 禁止复制。很多实际对象“被复制”是不合理的,因此需要禁止复制。C++98中将对应函数声明为private实现,C++11中有=delete修饰。
  • 引用计数。直到最后一个使用者停止使用,才释放相应资源。std::shared_ptr即带有引用计数的智能指针。
  • 复制资源。例如字符串对象的复制,可能希望内容也被复制一份用于后续的修改,即所谓的深拷贝(deep-copying)。在拷贝构造、拷贝赋值函数中实现底层资源的拷贝。
  • 转移所有权。C++98中auto_ptr的复制动作是这一语义。C++11引入了移动构造函数(move constructor)和移动赋值运算符函数(move operator assignment)之后,这才是已于区分和实现的。

15. 在资源管理类中提供对原始资源的访问

  • 标准库中的智能指针都提供了 get() 成员函数,用于取出原始指针。
  • 标准库中的std::unique_ptr更进一步提供了release()成员函数,取出原始指针的同时还会交出控制权。

16. 成对使用new和delete时要采取相同的形式

目的——为了防止内存泄露

  • newdelete对应,如p = new T;则要delete p;
  • new[]delete[]对应,如p = new T[N];则要delete [] p;

17. 以独立语句将new创建的对象放入智能指针

这里是说,如果使用智能指针管理new创建对象,就要把new表达式和智能指针创建放在一条语句中;

例如有如下测试程序:

#include <stdio.h>
#include <iostream>
#include <memory>
#include <string>
#include <stdexcept>

struct Foo {
    Foo(int n)
        : data(n)
    {
        printf("Foo_%p {data: %d} born!\n", this, data);
    }

    ~Foo()  { printf("Foo_%p {data: %d} die!\n", this, data); }

    int data;
};

int GetPriority(int n)
{
    static const int priorities[]{20, 21, 22};
    if (n < 0) {
        throw std::invalid_argument("n invalid: " + std::to_string(n));
    } else if (n > sizeof(priorities)/sizeof(priorities[0])) {
        throw std::out_of_range("n out of range: " + std::to_string(n));
    }
    return priorities[n];
}

void Process(const std::shared_ptr<Foo>& foo, int priority)
{
}

int main()
{
    std::shared_ptr<Foo> p0{new Foo(0)};

    try {
        std::shared_ptr<Foo> p1{new Foo(-1)};
        Process(p1, GetPriority(p1->data));
    } catch (std::exception& e) {
        std::cout << "exception raised:" << e.what() << std::endl;
    }

    try {
        Foo* p2 = new Foo(-2);
        Process(std::shared_ptr<Foo>(new Foo(-2)), GetPriority(p2->data));
    } catch (std::exception& e) {
        std::cout << "exception raised:" << e.what() << std::endl;
    }
    return 0;
}

这个程序的输出是:

Foo_0x56004c1f6e70 {data: 0} born!
Foo_0x56004c1f72c0 {data: -1} born!
Foo_0x56004c1f72c0 {data: -1} die!
exception raised:n invalid: -1
exception raised:n invalid: -2
Foo_0x56004c1f6e70 {data: 0} die!

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK