C++之智能指针auto_ptr

2023-10-28

当你在读这篇文章的时候,应该都有这样一个疑问?那就是为什么要使用智能指针。
我们先看这样一个示例:

#include <iostream>
#include <string>
#include  <exception> 

using std::string; 

void memory_demo1() {    
	string* str = new string("今天又找了一天的bug,太累了!!!");     
	std::cout << *str << std::endl;
	//并没有调用delete str,进行释放    
	return;
} 

int memory_demo2() {    
	string* str = new string("这个世界到处是坑啊,异常处理都要坑我!!!");
	     
	/*     
	* 程序这里省略执行了一段复杂的逻辑并会执行到throw这个函数    
	*/    
	{        
		throw exception("文件不存在");   
	}    
	
	std::cout << *str << std::endl;    
	delete str;	//虽然此处调用了,但执行到throw时就结束了,并不会执行到这一布    
	return 0;
} 

int main(){    
	memory_demo1();    
	try {        
		memory_demo2();    
	}    
	catch (exception e) {        
	std::cout<<"catch exception: "<<e.what()<<endl;    
	}     
	
	system("pause");    
	return 0;
}

这段程序如果乍一看是不是没有什么问题,也可以正常编译和运行。但这只是少量代码,体现不出来问题在哪。如果一涉及到工程级代码,那就很容易造成内存泄漏问题(真的是程序员最头疼的问题之一)。

对于上面问题,最简单的一个办法就是把string定义为auto变量。那在这个函数周期结束时就会自动的进行释放(局部变量)。

void memory_demo1() {
	//string* str = new string("今天又找了一天的bug,太累了!!!")    
	string str("今天又找了一天的bug,太累了!!!");    
	std::cout << str << std::endl;
	return;
} 
int memory_demo2() {    
	//string* str = new string("这个世界到处是坑啊,异常处理都要坑我!!!");
	string str("这个世界到处是坑啊,异常处理都要坑我!!!");
	...           
	return 0;
}

现在我们定义的是一个string(局部)对象,那在函数结束的时候,string这个函数内部会自己调用析构函数就行释放。

看到这,那是不是可以这样做:如果我们分配的动态内存都交给有生命周期的对象来处理,那么在对象过期时,让它的析构函数删除指向的内存,这看似是一个非常好的方案?

或许正是由于这样的想法,智能指针一词被那些C++的大牛们所实践出来。
智能指针也是通过这个原理来解决指针智能释放问题。

智能指针的原理:

直接点说就是资源分配即初始化RAII(Resource Acquisition Is Initialization):
定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放。

实现机制:利用类的构造和析构函数(释放资源)是由编译器自动调用的。

在C++标准库中主要有下面4个智能指针:

(1)C++98提供了auto_ptr的模板
(2)C++11 增加了unique_ptr、shared_ptr 和weak_ptr三种智能指针

其中:shared_ptr是引用计数的智能指针,被奉为裸指针的完美替身,因此被广泛使用。也可能正是这个原因,scope_ptr 和 weak_ptr似乎被大家遗忘了。

简单总结下这几个只智能指针

1.auto_ptr
管理权转移
带有缺陷的设计 ----->c++98
在任何情况下都不要使用

2.scoped_ptr(boost)
unique_ptr(c++11)
防拷贝—>简单粗暴设计—>功能不全。

3、shared_ptr(boost/c++11)
引用计数—>功能强大(支持拷贝、支持定制删除器)
缺陷---->循环引用(使用weak_ptr配合解决)。

下面来介绍这篇文章的主角:auto_ptr,剩下的三个会在后面的篇章中进行一一介绍。

auto_ptr

看到这,也许有人会问,既然上面都表明了任何情况下都不要使用,那为什么还要介绍,还要放到C++标准库里面呢?个人感觉或许是因为C++标准库里面的内容一经规定后就不允许修改了吧。这里就不对这个问题就行纠结了,对于auto_ptr,这里权当学习了解一下就好了。

定义:

auto_ptr 是c++ 98定义的智能指针模板,其定义了管理指针的对象,可以将new 获得(直接或间接)的地址赋给这种对象。当对象过期时,其析构函数将使用delete 来释放内存!

用法:

auto_ptr<类型> 变量名(new 类型)

注意
(1)std::auto_ptr 属于 STL,也在namespace std中,使用的时候要加上#include 头文件。
(2)由于源代码中构造函数声明为explicit的,因此不能通过隐式转换来构造,只能显式调用构造函数。

auto_ptr<string> pstr(new string("abcd"));  //  success
auto_ptr<string> pstr = new string("abcd"); //  error

例如:
auto_ptr str(new string(“今天又找了一天的bug,太累了!!!”));
//对比刚开始的示例使用string* str = new string(“今天又找了一天的bug,太累了!!!”);会造成内存泄漏问题。

讲解示例1.1如下:

#include <iostream>
#include <string>
#include <exception>
#include <memory>

using std::string;
class Test
{
public:
	Test() { cout << "test is construct" << endl;  num = 1; }
	~Test() { cout << "test is destruct" << endl; }
	int getNum() { return num; }
private:
	int num;
};

//用  法:    auto_ptr<类型> 变量名(new 类型)
void memory_demo1() {   
	//Test *test = new Test;	//代码1
 	auto_ptr<Test> test(new Test());//代码2	//创建对象
	
	cout<<test->getNum()<<endl;	//代码3
	//(*test).getNum();		//代码4
	
	//Test *temp = test.get();	//代码5
	//temp->getNum();

	//代码6
	//Test *tmp1 = test.release(); //取消智能指针对动态内存的托管,之前分配的内存必须手动释放
	//tmp1->getNum();
 	//delete tmp1;
 	
 	//代码7
 	//test.reset(); //括号内可以传递一个参数,默认参数是一个空指针
 	//test.reset(new Test());
	return;
} 

int memory_demo2()
{
	Test *t = new Test;
	{
		throw exception("文件不存在");
	}
	
	delete t;
 	return 0;
}

int main()
{
	memory_demo1();
	ty{
		memory_demo2();
	}catch (exception e) {
  		std::cout << "catch exception: " << e.what() << endl;
 	}

	system("pause");
 	return 0;
}

(1)如果将代码1放出来,代码2注释(没有使用智能指针的情况下),运行结果如下:在这里插入图片描述
结果显示只执行了构造函数,并没有自动执行析构函数

(2)如果将代码1注释,而放出来代码2,使用代码2替代代码1,结果如下:
在这里插入图片描述
结果显示既执行了构造,又自动执行了析构函数

这是怎么一回事呢,使用vs2015(其他的也可以),代码2处auto_ptr按F12进入源码。如下:
在这里插入图片描述
是实话这里的很多代码我自己也看不懂,但并不影响我们了解实现原理。看红色箭头的地方,此处是构造函数的地方。注意_Myptr(_Ptr),这里应该还挺好理解的,将我们外面的auto_ptr test(new Test());这个代码定义的对象,赋值到它内部。当看到源码实现最底下这里时:
在这里插入图片描述
是不是突然间感觉容易理解了很多。这不就是将它的类对象替换成前面我们在外面定义的对象吗?当它内部执行完成后,就会调用析构函数释放,这样不就能实现对象的自动释放了吗。

不知道在看auto_ptr源代码的时候有没有注意到里面这几个类方法
在这里插入图片描述
(3)当上面示例1.1在调用代码3的时候,其实auto_ptr源码里面重构了->,返回了一个get()方法,而内部get()的实现则返回了内部类对象,这样当外部示例1.1调用test->getNum()的时候,其他变相的还是使用传进去的test对象再调用这个函数。至于示例1.1中的代码4实现原理也是一样的。
注:以后可以使用对象调用.get()来判断智能指针是否为空,是否创建成功。
在示例1.1代码2之后可以调用test.get()来判断是否生成成功了。

(4)在这里插入图片描述既然(2)中说了get()返回的是内部类对象,那示例1.1中调用代码5肯定是可以行得通的。将代码5放出来后运行发现也是可以正常运行的。但这样做的意义并不大,不建议去使用。

(5)当示例1.1代码中放出来代码6,调用release时,通过源码可以看到:
原理就是定义一个此类型的临时指针变量,指向之前保存的指针的地址,然后将它(之前)的属性置为空指针,并将临时的返回了。但是它并没有帮我们去释放之前的地址。所以在代码6调用之后,我还加上了一个delete tmp1操作。即调用release时就相当于取消了智能指针对动态内存的托管,而且之前分配的内存必须手动释放。(个人感觉有点多此一举,不推荐)
realease实现的功能就是将原智能指针的控制权取消。

(6)当调用reset时(释放代码7).通过源码,可以看到还可以传递一个参数。当不传参数或者传递NULL时默认参数是一个空指针。此函数功能就是重置智能指针托管的内存地址,如果地址不一致,原来的会被析构掉。也就是说当传递一个空值时,会将原来的析构掉,将空值赋值给原来的值。通俗点就是:无参时智能指针会释放当前管理的内存取消对原对象的控制权。如果传递一个对象,则智能指针会释放当前原对象,来管理新传入的对象。

当调用代码7中test.reset(new Test())时,此时新对象会析构并替换掉原来的对象。(此时结果会调用两次构造和析构)
在这里插入图片描述

说到这里,对于auto_ptr的个人认识也差不多结束了。虽然auto_ptr叫智能智能,如果说它智能的话,那它真智能吗。在我看来无非就是利用对象析构的时候要调用析构函数,然后再利用析构函数帮我们做这个事情(释放内存)。

哦。对了。这里做一下用法的总结:(虽然没有什么用,因为它几乎被禁用了,而且shared_ptr也完美的替代了它。这里就当做一个知识的了解吧)

总结:

(1)尽可能不要将auto_ptr 变量定义为全局变量或指针
当设定为全局变量的时候,比如全局定义这样的一个对象:auto_ptr t(new Test()),那t这个对象只有在程序执行结束的时候才会被释放,就达不到我们使用它的目的和初衷。使用智能指针就没有意义了

(2)除非自己知道后果,否则不要把auto_ptr 智能指针赋值给同类型的另外一个智能指针

auto_ptr< Test> t(new Test());
auto_ptr< Test> t1;
t1 = t;

(3)不要定义指向智能指针对象的指针变量

auto_ptr<Test>* tp = new auto_ptr<Test>(new Test());

当这样使用的时候,运行结束时,C++根本不会去析构tp这个对象。因为后面new auto_ptr(new Test())也是动态内存分配的。那它也就成为了一个普通对象,也就自然不会去自动再去析构它。那它跟文章最开始写的new string也就没有区别了。

(4)想使用 std::auto_ptr 的限制感觉还真多,还不能用来管理堆内存数组,就算使用了还怕哪天一个不小心,就导致问题了。或许由于 std::auto_ptr 引发了诸多问题,而且一些设计并不是非常符合 C++ 编程思想。所以C++11 后auto_ptr 已经被“抛弃”,已使用unique_ptr替代
话说这点才是最重要的,说了这么多是不是等于白说了。话虽如此,但看到这里说明前面知识点已经看完了,就当学习知识了,对自己又没有坏处。

auto_ptr的补充

这里忘记说明了一个重要的知识点,或许这才是auto_ptr被unique_ptr取代的主要原因:
为了更直观的说明,以示例代码2.1讲解:

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

using std::string;
using std::vector;
using std::auto_ptr;

int main()
{
	//弊端1:复制或赋值都会改变资源的所有权
	auto_ptr<string> p1(new string("I 'm string1."));
 	auto_ptr<string> p2(new string("I 'm string2."));
 	printf("p1: %p\n", p1.get());	
 	printf("p2: %p\n", p2.get());	
 	
 	p1 = p2;	//代码1
 	printf("after p1 = p2\n");
 	printf("p1: %p\n", p1.get());	
 	printf("p2: %p\n", p2.get());	

	//弊端2
	vector<auto_ptr<string>> va;	
	auto_ptr<string> p3(new string("I 'm p3."));
	auto_ptr<string> p4(new string("I 'm p4."));
	va.push_back(p3); 	//代码2
 	va.push_back(p4);	//代码3
	//va.push_back(std::move(p3));  //代码4	//右值化后才能转换赋值 
 	//va.push_back(std::move(p4));	//代码5
 	 std::cout << "va[0]: " << *va[0] << std::endl;
	 std::cout << "va[1]: " << *va[1] << std::endl;

	//弊端3
	{
		auto_ptr<string> p5;
		string* str = new string("智能指针的内存管理陷阱");
		p5.reset(str);		//代码9
		{
			auto_ptr<string> p6;
			p6.reset(str);		//代码10
		}
		std::cout <<"str: " << *p5 << std::endl;//代码11
	}
	
	system("pause");
 	return 0;
}

运行结果如下:
在这里插入图片描述
这里可以清晰的看到在执行完代码1:p1 = p2后,p1的地址变为p2了,而p2的地址为空了。而这个时候如果再去使用p2进行操作时肯定就会报错的,至于报什么类型的错应该都能猜到。
(1)总结弊端1:当进行 p1= p2,复制或赋值都会改变资源的所有权,这估计是auto_ptr在C++11之后被抛弃的主要原因之一。

当将弊端1和3的代码全部注释,运行出来弊端2的代码。
在示例2.1上,代码2跟代码3按平时的写法貌似没有问题,但编译的时候却会报错。原因在于不支持左值操作,只有进行右值化后才能转换赋值。也就是上面会有代码4跟代码5的原因,它们是为了替代代码2和3而写上的。当使用代码4和5时,运行结果如下:
在这里插入图片描述
很正常的数据。还记得刚刚提到的弊端1吗?当添加上如下代码时,再去编译运行查看一下结果:

va[0] = va[1];		//代码6
std::cout << "va[0]: " << *va[0] << std::endl;		//代码7
std::cout << "va[1]: " << *va[1] << std::endl;		//代码8

在这里插入图片描述
再去源代码764查看:
在这里插入图片描述
归根结底,还是在于执行代码6后,再去访问代码8时,它已经是一个空值了,它的地址被赋值到了va[0]了,而空值是不允许被访问使用的。
(2)总结弊端2:在 STL 容器中使用auto_ptr存在重大风险,因为容器内的元素必需支持可复制(copy constructable)和可赋值(assignable),STL容器中的元素经常要支持拷贝,赋值等操作,在这过程中auto_ptr会传递所有权,而弊端1中明确的说到了赋值和复制都会改变资源的所有权。所以一般情况下尽量不要在STL容器中使用auto_ptr。

当将弊端1和2的代码注释,运行弊端3下面的代码时,看起来并没有错误才是,但运行的结果却是失败的。如下
在这里插入图片描述

那造成这样的原因是什么呢?我们注意一下弊端3下面的代码9,代码10,代码11。当执行完代码9时,相当于初始化p5,将str这个对象返回给p5这个对象,相当于替换吧。(reset内部实现就是将原来的对象delete,并将新传入的对象交给原来的对象)。但当执行完代码10是,就是将str这个对象又交给了p6,由p6去管理。再执行代码11之前,由于加了括号是局部对象,当出了括号p6就会自动执行析构,即同时会delete掉str这个对象。所以当执行代码11时,由于p5内部的地址被替换为了str(它已经被p6的析构释放掉了),所以会报错。
(3)弊端总结3:auto_ptr不能共享所有权,不能把同一段内存交给多个auto_ptr 变量去管理。

(4)auto_ptr不能指向数组,不支持对象数组的内存管理,因为auto_ptr在析构的时候只是调用delete,而数组应该要调用delete[]。

auto_ptr<int[]> ai(new int[5]);

当添加这种类似的代码也是会报错的。不能这样用。

所以,C++11用更严谨的unique_ptr 取代了auto_ptr!
好了,对于auto_ptr的用法就到这里了,其他的我自己也不知道了。

下面是对C++11的三种智能指针介绍,觉得写的不错的可以继续阅读:

C++之智能指针unique_ptr
C++之智能指针shared_ptr
C++之智能指针weak_ptr

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++之智能指针auto_ptr 的相关文章

  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • C++ 求二维数组每一行的最大值

    我已经设法用这个找到我的二维数组的每一行的最小值 void findLowest int A Cm int n int m int min A 0 0 for int i 0 i lt n i for int j 0 j lt m j if
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • c# Asp.NET MVC 使用FileStreamResult下载excel文件

    我需要构建一个方法 它将接收模型 从中构建excel 构建和接收部分完成没有问题 然后使用内存流导出 让用户下载它 不将其保存在服务器上 我是 ASP NET 和 MVC 的新手 所以我找到了指南并将其构建为教程项目 public File
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • 可空属性与可空局部变量

    我对以下行为感到困惑Nullable types class TestClass public int value 0 TestClass test new TestClass Now Nullable GetUnderlyingType
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM
  • EPPlus Excel 更改单元格颜色

    我正在尝试将给定单元格的颜色设置为另一个单元格的颜色 该单元格已在模板中着色 但worksheet Cells row col Style Fill BackgroundColor似乎没有get财产 是否可以做到这一点 或者我是否必须在互联
  • 作为字符串的动态属性名称

    使用 DocumentDB 创建新文档时 我想设置属性名称动态地 目前我设置SomeProperty 像这样 await client CreateDocumentAsync dbs db colls x new SomeProperty
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz
  • 如何在 C# 中播放在线资源中的 .mp3 文件?

    我的问题与此非常相似question https stackoverflow com questions 7556672 mp3 play from stream on c sharp 我有音乐网址 网址如http site com aud

随机推荐

  • VMWare里Linux的网络配置

    今天终于把十几天前安装在VMWare里的Linux的网络配置搞定了 高兴啊 刚使用虚拟机时 就被它神奇的虚拟功能所着迷 因为一直想在电脑里装Linux 可是由于它与Windows的不兼容 怕一安装就把原来的系统破坏 但是在虚拟机里真的能很好
  • C++_自定义函数实现返回两个数中的较小数

    本文仅仅发布在CSDN我的博客 点击打开链接 http blog csdn net pythontojava viewmode contents 转载请注明出处 我用的IDE是VS2013 代码在vc 6 0不能编译 要把int tmain
  • python怎样用stata_Python 读取stata文件

    利用Python读取stata文件 并防止中文乱码 其中 load large dta用于读取stata文件 decode str用于编译中文字符串 import pandas as pd import numpy as np import
  • Java反射详解

    目录 反射是框架设计的灵魂 一 反射的概述 反射就是把java类中的各种成分映射成一个个的Java对象 二 反射机制有什么用 三 Java反射机制的优点 四 反射机制相关的重要的类有哪些 编辑 Class类 接下来 我们已Student实体
  • 硬件系统工程师宝典(40)-----Datasheet要全都看完吗?

    各位同学大家好 欢迎继续做客电子工程学习圈 今天我们继续来讲这本书 硬件系统工程师宝典 上篇我们介绍了ESD对电路的影响以及ESD器件的选型 今天我们来讲一讲Datasheet要怎么看 我们在进行IC原理图设计时 经常需要查看IC的Data
  • qt通过Lable设置背景图片

    在lable中可以添加resoures中包含的图片 设置图片 QPixmap pix new QPixmap 1 jpg 添加resources中的文件 QSize sz ui gt background lable gt size ui
  • 成年人的自由,从学会拒绝开始

    一位读者问我 润总 我总是不好意思 也不敢 拒绝别人 常常被迫扭曲自己 做一些不情愿的事 怎么办 怎么才能得体地拒绝别人呢 今天我想告诉你一个拒绝别人的心法 坚定而柔软 1 什么叫做坚定而柔软 坚定 代表不左右动摇 不模棱两可 但是坚定 并
  • mnist数据集介绍

    参考博客 https blog csdn net tostq article details 51786265 参考代码 https github com tostq DeepLearningC tree master CNN MINST数
  • 搭建符号服务器 (Windows)

    开网站 安装IIS 添加一个网站 配置好物理路径 添加MIME 扩展名为 类型为 application octet stream 即允许下载所有文件 好了 就那么简单 把pdb发布到网站中 我这里建立了一个名叫 test 的网站 物理路径
  • Human3.6m数据集

    最近用到了Human3 6数据集 整理一下链接 1 原数据链接 http vision imar ro human3 6m 需要注册申请 时间可能很长 也很大 看别的帖子说很长 没试 好像是cdf文件 2 3d pose baseline
  • java中构造器(Constructor)

    大部分内容转自 http tech it168 com j 2006 05 18 200605181021879 shtml 构造器是一个创建对象时被自动调用的特殊方法 为的是初始化 构造器的名称应与类的名称一致 当创建一个个对象时 系统会
  • 量化投资学习-12:股市的量化交易是情绪化交易的克星之一

    江湖传言 散户的情绪化追涨杀跌交易是散户赚不到钱 甚至是小亏的根本原因 散户的不懂得止损的情绪化操作是散户深套 大亏的根本原因 终止 散户亏损的内因是 散户的自身的非量化的 非理性的 情绪化交易 量化交易是散户的救星 一直以来 认为庄家是散
  • Python实现ip段地址

    author skate time 2014 10 13 Python实现ip段地址的打印 如10 10 10 1 10 10 10 10 usr bin env python encoding UTF 8 Author Skate def
  • VMtools的安装

    基本概述 1 可以实现命令在Windows与centos上复制粘贴 2 可以实现Windows与centos上文件夹共享 VMtools的安装步骤 1 进入Centos系统 2 点击VM菜单的安装VMware Tools 因为我已经安装了
  • 一文彻底理解DMA

    DMA Direct Memory Acess 1 什么是DMA 有什么作用 2 DMA传输过程简述 2 1 DMA普通传输过程 2 2 DMA指针递增传输过程 2 3 DMA循环传输过程 2 4 DMA双缓冲区传输过程 3 STM32F4
  • 使用arraycopy方法复制数组

    6 使用arraycopy方法复制数组 package array public class array public static void main String args TODO Auto generated method stub
  • 目标检测中Anchor如何映射到原图

    利用深度学习进行目标检测一般需要经过较深的卷积神经网络 而卷积本身就有位置不变性 会将原图中的某块区域映射为特征图上的某个点 anchor和特征图的关系 既然anchor是特征图对应像素点在原图的某个区域 那么是怎样的对应关系呢 现在假设某
  • 下载R包遇到的问题用这个方法解决了!!!

    之前我一直以为一个镜像源能适用于下载所有的R包 然而最近两天在线下载R包没有一次成功的 也改了很多次镜像源 然而每次都报错 unable to access index for repository http streaming stat
  • GD32替代STM32使用Cube MX的HAL库开发

    目录 一 STM32F103与GD32F103 差别比较 二 GD32使用CubeMX配置 1 配置单片机型号 2 晶振配置 3 其它配置 三 GD32使用Keil配置 1 更改型号为GD32芯片 2 编译下载 四 例程下载链接 一 STM
  • C++之智能指针auto_ptr

    当你在读这篇文章的时候 应该都有这样一个疑问 那就是为什么要使用智能指针 我们先看这样一个示例 include