C++Primer_第12章_动态内存

首先回顾一下C语言malloc函数,关于malloc的一个简单示例:

#include<stdio.h>  
#include<malloc.h>  
int main()  
{  
    char *p;  
   
    p=(char *)malloc(100);  
    if(p)  
        printf("Memory Allocated at: %x/n",p);  
    else  
        printf("Not Enough Memory!/n");  
    free(p);  
    return 0;  
}

一、动态内存与智能指针

shared_ptr允许多个指针指向同一个对象;

unique_ptr则独占所指向的对象;

weak_ptr弱引用,指向shared_ptr所管理的对象,

这三种类型都包含在#include<memory>.

二、shared_ptr

shared_ptr<string> p1; // shared_ptr that can point at a string
shared_ptr<list<int>> p2; // shared_ptr that can point at a list of ints

      p    将p用作一个条件判断,p指向一个对象则为true.

      *p  解引用p,获得它指向的对象

// if p1 is not null, check whether it's the empty string
if (p1 && p1->empty())
*p1 = "hi"; // if so, dereference p1 to assign a new value to that string

      最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准库函数,

      此函数分配一个对象并初始化它,返回指向此对象的shared_ptr

// shared_ptr that points to an int with value 42
shared_ptr<int> p3 = make_shared<int>(42);
// p4 points to a string with value 9999999999
shared_ptr<string> p4 = make_shared<string>(10, '9');

      简便起见或者用auto,

// p6 points to a dynamically allocated, empty vector<string>
auto p6 = make_shared<vector<string>>();

      当进行拷贝或赋值操作时,每个shared_ptr都会记录有多少个其他shared_ptr指向相同的对象,可以认为有一个关联的计数器,引用计数reference count.

      shared_ptr的析构函数会递减它所指向的对象的引用计数,如果引用计数变为0,shared_ptr的析构函数就会销毁对象,并释放它所占用的内存。

void use_factory(T arg)
{
shared_ptr<Foo> p = factory(arg);
// use p
} // p goes out of scope; the memory to which p points is automatically freed//Because p is local to use_factory
shared_ptr<Foo> use_factory(T arg)
{
shared_ptr<Foo> p = factory(arg);
// use p
return p; // reference count is incremented when we return p
} // p goes out of scope; the memory to which p points is not freed
//In this version, the return statement in use_factory returns a copy of p 
//to its caller. Copying a shared_ptr adds to the reference count of that
//object.
      使用动态内存的一个常见原因是允许多个对象共享相同的状态。

三、直接管理内存

      delete表达式执行两个动作:销毁给定的指针指向的对象;释放对应的内存。

      使用newdelete管理动态内存三个常见问题:

      1.忘记delete内存,内存泄漏。

      2.使用已释放的对象。

      3.同一块内存释放两次。

坚持只使用智能指针,就可以避免所有这些问题。

      delete之后,指针虽然无效,但是指针仍有可能保存着地址,即空悬指针:

int *p(new int(42)); // p points to dynamic memory
auto q = p; // p and q point to the same memory
delete p; // invalidates both p and q
p = nullptr; // indicates that p is no longer bound to an object

      本例中,p和q指向相同的动态分配对象。delete此内存,然后将p置为nullptr,指出它不再指向任何对象。

      但是释放p指向的内存时,q也变为无效了!,在实际系统中,查找指向相同内存的所有指针是异常困难的。

四、范例应用

    使用内置指针:

/*
 Write a function that returns a dynamically allocated vector
of ints. Pass that vector to another function that reads the standard input
to give values to the elements. Pass the vector to another function to print
the values that were read. Remember to delete the vector at the
appropriate time.
*/

#include<iostream>
#include<vector>
#include<memory>
#include<string>
using std::vector;
using std::string;

//返回一个动态分配的int的vector
vector<int>*dynamic_vector_generator()
{
	vector<int>*ptr_v = new vector<int>();
	return ptr_v;
}

//将上面vector传递给另一个函数,并读取输入,存入vector
void dynamic_vector_processor(vector<int>*ptr_v)
{
	int i;
	std::cout << "plz enter:\n";
	while (std::cin >> i && i != 999)
		ptr_v->push_back(i);//(*ptr_v).push_back(i);
}

//传入另一个函数打印输入的vector
void dynamic_vector_printer(vector<int>* ptr_v)
{
	for (const auto &i : *ptr_v)
		std::cout << i << "  ";
	std::cout << "\n";
}
int main()
{
	vector<int>*ptr_vi = dynamic_vector_generator();
	dynamic_vector_processor(ptr_vi);
	dynamic_vector_printer(ptr_vi);

	delete ptr_vi;
	ptr_vi = nullptr;

	
	return 0;

}
    使用 shared_ptr的版本
shared_ptr<vector<int> >dynamic_vector_generator_sptr()
{
	return make_shared<vector<int>>();
}

void dynamic_vector_processor_sptr(shared_ptr<vector<int>> sptr_vi)
{
	int i;
	std::cout << "plz enter:\n";
	while (std::cin >> i && i != 999)
		sptr_vi->push_back(i);
}

void dynamic_vector_printer_sptr(const shared_ptr<vector<int>> sptr_vi)
{
	for (const auto& e : *sptr_vi)
		std::cout << e << ", ";
	std::cout << "\n";
}

int main()
{
	auto sptr = dynamic_vector_generator_sptr();
	dynamic_vector_processor_sptr(sptr);
	dynamic_vector_printer_sptr(sptr);

	return 0;
}


猜你喜欢

转载自blog.csdn.net/MC_007/article/details/80342798