from: http://www.codeproject.com/Articles/541067/Cplusplus-Smart-Pointers
Introduction
Ooops. Yet another article on smart pointers of C++11. Nowadays I hear a lot of people talking about the new C++ standard which is nothing but C++0x/C++11. I went through some of the language features of C++11 and it's really an amazing work. I'll focus only on the smart pointers section of C++11.
Background
What are the issues with normal/raw/naked pointers?
Let's go one by one.
People refrain from using pointers as they give a lot of issues if not handled properly. That's why newbie programmers dislike pointers. Many issues are involved with pointers like ensuring the lifetime of objects referred to by pointers, dangling references, and memory leaks.
Dangling reference is caused if a memory block is pointed by more than one pointer variable and if one of the pointers is released without letting know the other pointer. As all of you know, memory leaks occur when a block of memory is fetched from the heap and is not released back.
People say, I write clean and error proof code, why should I use smart pointers? And a programmer asked me, "Hey, here is my code. I fetched the memory from the heap, manipulated it, and after that I released it properly. What is the need of a smart pointer? "
void Foo( ) { int* iPtr = new int[5]; //manipulate the memory block . . . delete[ ] iPtr; }
The above code works fine and memory is released properly under ideal circumstances. But think of the practical environment of code execution. The instructions between memory allocation and releasing can do nasty things like accessing an invalid memory location, dividing by zero, or say another programmer pitching into your program to fix a bug and adding a premature return
statement based on some condition.
In all the above cases, you will never reach the point where the memory is released. This is because the first two cases throw an exception whereas the third one is a premature return. So the memory gets leaked while the program is running.
The one stop solution for all of the above issues is Smart Pointers [if they are really smart enough].
What is a smart pointer?
Smart pointer is a RAII modeled class to manage dynamically allocated memory. It provides all the interfaces provided by normal pointers with a few exceptions. During construction, it owns the memory and releases the same when it goes out of scope. In this way, the programmer is free about managing dynamically allocated memory.
C++98 has introduced the first of its kind called auto_ptr
.
auto_ptr
Let's see the use of auto_ptr
and how smart it is to resolve the above issues.
class Test { public: Test(int a = 0 ) : m_a(a) { } ~Test( ) { cout<<"Calling destructor"<<endl; } public: int m_a; }; void main( ) { std::auto_ptr<Test> p( new Test(5) ); cout<<p->m_a<<endl; }
The above code is smart to release the memory associated with it. What we did is, we fetched a memory block to hold an object of type Test
and associated it with auto_ptr p
. So when p
goes out of scope, the associated memory block is also released.

//*************************************************************** class Test { public: Test(int a = 0 ) : m_a(a) { } ~Test( ) { cout<<"Calling destructor"<<endl; } public: int m_a; }; //*************************************************************** void Fun( ) { int a = 0, b= 5, c; if( a ==0 ) { throw "Invalid divisor"; } c = b/a; return; } //*************************************************************** void main( ) { try { std::auto_ptr<Test> p( new Test(5) ); Fun( ); cout<<p->m_a<<endl; } catch(...) { cout<<"Something has gone wrong"<<endl; } }
In the above case, an exception is thrown but still the pointer is released properly. This is because of stack unwinding which happens when an exception is thrown. As all local objects belonging to the try
block are destroyed, p
goes out of scope and it releases the associated memory.
Issue 1: So far auto_ptr
is smart. But it has more fundamental flaws over its smartness. auto_ptr
transfers the ownership when it is assigned to another auto_ptr
. This is really an issue while passing the auto_ptr
between the functions. Say, I have an auto_ptr
in Foo( )
and this pointer is passed another function say Fun( )
from Foo
. Now once Fun( )
completes its execution, the ownership is not returned back to Foo
.
//*************************************************************** class Test { public: Test(int a = 0 ) : m_a(a) { } ~Test( ) { cout<<"Calling destructor"<<endl; } public: int m_a; }; //*************************************************************** void Fun(auto_ptr<Test> p1 ) { cout<<p1->m_a<<endl; } //*************************************************************** void main( ) { std::auto_ptr<Test> p( new Test(5) ); Fun(p); cout<<p->m_a<<endl; }
The above code causes a program crash because of the weird behavior of auto_ptr
. What happens is that, p
owns a memory block and when Fun
is called, p
transfers the ownership of its associated memory block to the auto_ptr
p1
which is the copy of p
. Now p1
owns the memory block which was previously owned by p
. So far it is fine. Nowfun
has completed its execution, and p1
goes out of scope and the memory blocked is released. How about p
? p
does not own anything, that is why it causes a crash when the next line is executed which accesses p
thinking that it owns some resource.
Issue 2: Yet another flaw. auto_ptr
cannot be used with an array of objects. I mean it cannot be used with the operator new[]
.
//*************************************************************** void main( ) { std::auto_ptr<Test> p(new Test[5]); }
The above code gives a runtime error. This is because when auto_ptr
goes out of scope, delete
is called on the associated memory block. This is fine if auto_ptr
owns only a single object. But in the above code, we have created an array of objects on the heap which should be destroyed using delete[ ]
and not delete
.
Issue 3: auto_ptr
cannot be used with standard containers like vector, list, map, etc.
As auto_ptr
is more error prone and it will be deprecated, C++ 11 has come with a new set of smart pointers, each has its own purpose.
shared_ptr
unique_ptr
weak_ptr
shared_ptr
OK, get ready to enjoy the real smartness. The first of its kind is shared_ptr
which has the notion called shared ownership. The goal of shared_ptr
is very simple: Multiple shared pointers can refer to a single object and when the last shared pointer goes out of scope, memory is released automatically.
Creation:
void main( ) { shared_ptr<int> sptr1( new int ); }
Make use of the make_shared
macro which expedites the creation process. As shared_ptr
allocates memory internally, to hold the reference count, make_shared( )
is implemented in a way to do this job effectively.
void main( ) { shared_ptr<int> sptr1 = make_shared<int>(100); }
The above code creates a shared_ptr
which points to a memory block to hold an integer with value 100 and reference count 1. If another shared pointer is created out of sptr1
, the reference count goes up to 2. This count is known as strong reference. Apart from this, the shared pointer has another reference count known as weak reference, which will be explained while visiting weak pointers.
You can find out the number of shared_ptr
s referring to the resource by just getting the reference count by callinguse_count( )
. And while debugging, you can get it by watching the stong_ref
of the shared_ptr
.
Destruction:
shared_ptr
releases the associated resource by calling delete
by default. If the user needs a different destruction policy, he/she is free to specify the same while constructing the shared_ptr
. The following code is a source of trouble due to the default destruction policy:
class Test { public: Test(int a = 0 ) : m_a(a) { } ~Test( ) { cout<<"Calling destructor"<<endl; } public: int m_a; }; void main( ) { shared_ptr<Test> sptr1( new Test[5] ); }
Because shared_ptr
owns an array of objects, it calls delete
when it goes out of scope. Actually, delete[ ]
should have been called to destroy the array. The user can specify the custom deallocator by a callable object, i.e., a function, lambda expression, function object.
void main( ) { shared_ptr<Test> sptr1( new Test[5], [ ](Test* p) { delete[ ] p; } ); }
The above code works fine as we have specified the destruction should happen via delete[]
.
Interface
shared_ptr
provides dereferencing operators *
, ->
like a normal pointer provides. Apart from that it provides some more important interfaces like:
-
get( )
: To get the resource associated with theshared_ptr
. -
reset( )
: To yield the ownership of the associated memory block. If this is the lastshared_ptr
owning the resource, then the resource is released automatically. -
unique
: To know whether the resource is managed by only thisshared_ptr
instance. -
operator bool
: To check whether theshared_ptr
owns a memory block or not. Can be used with anif
condition.
OK, that is all about shared_ptr
s. But shared_ptr
s too have a few issues:.
Issues:
- If a memory is block is associated with
shared_ptr
s belonging to a different group, then there is an error. Allshared_ptr
s sharing the same reference count belong to a group. Let's see an example.
void main( ) { shared_ptr<int> sptr1( new int ); shared_ptr<int> sptr2 = sptr1; shared_ptr<int> sptr3; sptr3 = sptr2; }
The below table gives you the reference count values for the above code.
All shared_ptr
s share the same reference count hence belonging to the same group. The above code is fine. Let's see another piece of code.
void main( ) { int* p = new int; shared_ptr<int> sptr1( p); shared_ptr<int> sptr2( p ); }
The above piece of code is going to cause an error because two shared_ptr
s from different groups share a single resource. The below table gives you a picture of the root cause.
To avoid this, better not create the shared pointers from a naked pointer.
- There is another issue involved with creating a shared pointer from a naked pointer. In the above code, consider that only one shared pointer is created using
p
and the code works fine. Consider by mistake if a programmer deletes the naked pointerp
before the scope of the shared pointer ends. Oooppss!!! Yet another crash.. - Cyclic Reference: Resources are not released properly if a cyclic reference of shared pointers are involved. Consider the following piece of code.
class B; class A { public: A( ) : m_sptrB(nullptr) { }; ~A( ) { cout<<" A is destroyed"<<endl; } shared_ptr<B> m_sptrB; }; class B { public: B( ) : m_sptrA(nullptr) { }; ~B( ) { cout<<" B is destroyed"<<endl; } shared_ptr<A> m_sptrA; }; //*********************************************************** void main( ) { shared_ptr<B> sptrB( new B ); shared_ptr<A> sptrA( new A ); sptrB->m_sptrA = sptrA; sptrA->m_sptrB = sptrB; }
The above code has cyclic reference. I mean class A holds a shared pointer to B and class B holds a shared pointer to A. In this case, the resource associated with both sptrA
and sptrB
are not released. Refer to the below table.
Reference counts for both sptrA
and sptrB
go down to 1 when they go out of scope and hence the resources are not released!!!!!
To resolve the cyclic reference, C++ provides another smart pointer class called weak_ptr
.
Weak_Ptr
A weak pointer provides sharing semantics and not owning semantics. This means a weak pointer can share a resource held by a shared_ptr
. So to create a weak pointer, some body should already own the resource which is nothing but a shared pointer.
A weak pointer does not allow normal interfaces supported by a pointer, like calling *
, ->
. Because it is not the owner of the resource and hence it does not give any chance for the programmer to mishandle it. Then how do we make use of a weak pointer?
The answer is to create a shared_ptr
out of a weak _ptr
and use it. Because this makes sure that the resource won't be destroyed while using by incrementing the strong reference count. As the reference count is incremented, it is sure that the count will be at least 1 till you complete using the shared_ptr
created out of the weak_ptr
. Otherwise what may happen is while using the weak_ptr
, the resource held by the shared_ptr
goes out of scope and the memory is released which creates chaos.
Creation
A weak pointer constructor takes a shared pointer as one of its parameters. Creating a weak pointer out of a shared pointer increases the weak reference counter of the shared pointer. This means that the shared pointer shares it resource with another pointer. But this counter is not considered to release the resource when the shared pointer goes out of scope. I mean if the strong reference of the shared pointer goes to 0, then the resource is released irrespective of the weak reference value.
void main( ) { shared_ptr<Test> sptr( new Test ); weak_ptr<Test> wptr( sptr ); weak_ptr<Test> wptr1 = wptr; }
We can watch the reference counters of the shared/weak pointer.
Assigning a weak pointer to another weak pointer increases the weak reference count.
So what happens when a weak pointer points to a resource held by the shared pointer and the shared pointer destroys the associated resource when it goes out of scope? The weak pointer gets expired.
How to check whether the weak pointer is pointing to a valid resource? There are two ways:
- Call the
use_count( )
method to know the count. Note that this method returns the strong reference count and not the weak reference. - Call the
expired( )
method. This is faster than callinguse_count( )
.
To get a shared_ptr
from a weak_ptr
call lock( )
or directly casting the weak_ptr
to shared_ptr
.
void main( ) { shared_ptr<Test> sptr( new Test ); weak_ptr<Test> wptr( sptr ); shared_ptr<Test> sptr2 = wptr.lock( ); }
Getting the shared_ptr
from the weak_ptr
increases the strong reference as said earlier.
Now let's see how the cyclic reference issue is resolved using the weak_ptr
.

class B; class A { public: A( ) : m_a(5) { }; ~A( ) { cout<<" A is destroyed"<<endl; } void PrintSpB( ); weak_ptr<B> m_sptrB; int m_a; }; class B { public: B( ) : m_b(10) { }; ~B( ) { cout<<" B is destroyed"<<endl; } weak_ptr<A> m_sptrA; int m_b; }; void A::PrintSpB( ) { if( !m_sptrB.expired() ) { cout<< m_sptrB.lock( )->m_b<<endl; } } void main( ) { shared_ptr<B> sptrB( new B ); shared_ptr<A> sptrA( new A ); sptrB->m_sptrA = sptrA; sptrA->m_sptrB = sptrB; sptrA->PrintSpB( ); }
Unique_ptr
This is almost a kind of replacement to the error prone auto_ptr
. unique_ptr
follows the exclusive ownership semantics, i.e., at any point of time, the resource is owned by only one unique_ptr
. When auto_ptr
goes out of scope, the resource is released. If the resource is overwritten by some other resource, the previously owned resource is released. So it guarantees that the associated resource is released always.
Creation
unique_ptr
is created in the same way as shared_ptr
except it has an additional facility for an array of objects.
unique_ptr<int> uptr( new int );
The unique_ptr
class provides the specialization to create an array of objects which calls delete[ ]
instead ofdelete
when the pointer goes out of scope. The array of objects can be specified as a part of the template parameter while creating the unique_ptr
. In this way, the programmer does not have to provide a custom deallocator, as unique_ptr
does it.
unique_ptr<int[ ]> uptr( new int[5] );
Ownership of the resource can be transferred from one unique_ptr
to another by assigning it.
Keep in mind that unique_ptr
does not provide you copy semantics [copy assignment and copy construction is not possible] but move semantics.
In the above case, if upt3
and uptr5
owns some resource already, then it will be destroyed properly before owning a new resource.
Interface
The interface that unique_ptr
provides is very similar to the ordinary pointer but no pointer arithmetic is allowed.
unique_ptr
provides a function called release
which yields the ownership. The difference between release( )
and reset( )
, is release
just yields the ownership and does not destroy the resource whereas reset
destroys the resource.
Which one to use?
It purely depends upon how you want to own a resource. If shared ownership is needed then go for shared_ptr
, otherwise unique_ptr
.
Apart from that, shared_ptr
is a bit heavier than unique_ptr
because internally it allocates memory to do a lot of book keeping like strong reference, weak reference, etc. But unique_ptr
does not need these counters as it is the only owner for the resource.
Using the code
I have attached the worked out code to explain the details of each pointer. I have added enough comments to each instruction. Ping me back if you find any problems with the code. The weak pointer example demonstrates the problems with shared pointers in the case of cyclic reference and how the weak pointer resolves it.
相关推荐
# 【spring-ai-bedrock-converse-1.0.0-M7.jar中文文档.zip】 中包含: 中文文档:【spring-ai-bedrock-converse-1.0.0-M7-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【spring-ai-bedrock-converse-1.0.0-M7.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【spring-ai-bedrock-converse-1.0.0-M7.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【spring-ai-bedrock-converse-1.0.0-M7.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【spring-ai-bedrock-converse-1.0.0-M7-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: spring-ai-bedrock-converse-1.0.0-M7.jar中文文档.zip,java,spring-ai-bedrock-converse-1.0.0-M7.jar,org.springframework.ai,spring-ai-bedrock-converse,1.0.0-M7,org.springframework.ai.bedrock.converse,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,springframework,spring,ai,bedrock,converse,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【spring-ai-bedrock-converse-1
房地产 -可视化管理课件.ppt
# 【tokenizers-***.jar***文档.zip】 中包含: ***文档:【tokenizers-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【tokenizers-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【tokenizers-***.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【tokenizers-***.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【tokenizers-***-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: tokenizers-***.jar***文档.zip,java,tokenizers-***.jar,ai.djl.huggingface,tokenizers,***,ai.djl.engine.rust,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,djl,huggingface,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【tokenizers-***.jar***文档.zip】,再解压其中的 【tokenizers-***-javadoc-API文档-中文(简体)版.zip】,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件; # Maven依赖: ``` <dependency> <groupId>ai.djl.huggingface</groupId> <artifactId>tokenizers</artifactId> <version>***</version> </dependency> ``` # Gradle依赖: ``` Gradle: implementation group: 'ai.djl.huggingface', name: 'tokenizers', version: '***' Gradle (Short): implementation 'ai.djl.huggingface:tokenizers:***' Gradle (Kotlin): implementation("ai.djl.huggingface:tokenizers:***") ``` # 含有的 Java package(包): ``` ai.djl.engine.rust ai.djl.engine.rust.zoo ai.djl.huggingface.tokenizers ai.djl.huggingface.tokenizers.jni ai.djl.huggingface.translator ai.djl.huggingface.zoo ``` # 含有的 Java class(类): ``` ai.djl.engine.rust.RsEngine ai.djl.engine.rust.RsEngineProvider ai.djl.engine.rust.RsModel ai.djl.engine.rust.RsNDArray ai.djl.engine.rust.RsNDArrayEx ai.djl.engine.rust.RsNDArrayIndexer ai.djl.engine.rust.RsNDManager ai.djl.engine.rust.RsSymbolBlock ai.djl.engine.rust.RustLibrary ai.djl.engine.rust.zoo.RsModelZoo ai.djl.engine.rust.zoo.RsZooProvider ai.djl.huggingface.tokenizers.Encoding ai.djl.huggingface.tokenizers.HuggingFaceTokenizer ai.djl.huggingface.tokenizers.HuggingFaceTokenizer.Builder ai.djl.hu
内容概要:本文详细介绍了如何使用MATLAB构建和应用BP神经网络预测模型。首先,通过读取Excel数据并进行预处理,如归一化处理,确保数据的一致性和有效性。接着,配置网络结构,选择合适的训练算法(如SCG),设置训练参数(如最大迭代次数、目标误差等)。然后,进行模型训练,并通过可视化窗口实时监控训练过程。训练完成后,利用测试集评估模型性能,计算均方误差(MSE)和相关系数(R²),并通过图表展示预测效果。最后,将训练好的模型保存以便后续调用,并提供了一个简单的预测函数,确保新数据能够正确地进行归一化和预测。 适合人群:具有一定MATLAB基础,从事数据分析、机器学习领域的研究人员和技术人员。 使用场景及目标:适用于需要对多维数据进行预测的任务,如电力负荷预测、金融数据分析等。主要目标是帮助用户快速搭建一个可用的BP神经网络预测系统,提高预测准确性。 其他说明:文中提供了完整的代码框架和详细的注释,便于理解和修改。同时,强调了数据预处理的重要性以及一些常见的注意事项,如数据量的要求、归一化的必要性等。
# 【tokenizers-***.jar***文档.zip】 中包含: ***文档:【tokenizers-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【tokenizers-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【tokenizers-***.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【tokenizers-***.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【tokenizers-***-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: tokenizers-***.jar***文档.zip,java,tokenizers-***.jar,ai.djl.huggingface,tokenizers,***,ai.djl.engine.rust,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,djl,huggingface,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【tokenizers-***.jar***文档.zip】,再解压其中的 【tokenizers-***-javadoc-API文档-中文(简体)版.zip】,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件; # Maven依赖: ``` <dependency> <groupId>ai.djl.huggingface</groupId> <artifactId>tokenizers</artifactId> <version>***</version> </dependency> ``` # Gradle依赖: ``` Gradle: implementation group: 'ai.djl.huggingface', name: 'tokenizers', version: '***' Gradle (Short): implementation 'ai.djl.huggingface:tokenizers:***' Gradle (Kotlin): implementation("ai.djl.huggingface:tokenizers:***") ``` # 含有的 Java package(包): ``` ai.djl.engine.rust ai.djl.engine.rust.zoo ai.djl.huggingface.tokenizers ai.djl.huggingface.tokenizers.jni ai.djl.huggingface.translator ai.djl.huggingface.zoo ``` # 含有的 Java class(类): ``` ai.djl.engine.rust.RsEngine ai.djl.engine.rust.RsEngineProvider ai.djl.engine.rust.RsModel ai.djl.engine.rust.RsNDArray ai.djl.engine.rust.RsNDArrayEx ai.djl.engine.rust.RsNDArrayIndexer ai.djl.engine.rust.RsNDManager ai.djl.engine.rust.RsSymbolBlock ai.djl.engine.rust.RustLibrary ai.djl.engine.rust.zoo.RsModelZoo ai.djl.engine.rust.zoo.RsZooProvider ai.djl.huggingface.tokenizers.Encoding ai.djl.huggingface.tokenizers.HuggingFaceTokenizer ai.djl.huggingface.tokenizers.HuggingFaceTokenizer.Builder ai.djl.hu
内容概要:本文探讨了电动汽车(EV)对IEEE 33节点电网的影响,特别是汽车负荷预测与节点潮流网损、压损计算。通过蒙特卡洛算法模拟电动汽车负荷的时空特性,研究了四种不同场景下电动汽车接入电网的影响。具体包括:负荷接入前后的网损与电压计算、不同节点接入时的变化、不同时段充电的影响以及不同负荷大小对电网的影响。通过这些分析,揭示了电动汽车充电行为对电网的具体影响机制,为未来的电网规划和优化提供了重要参考。 适合人群:从事电力系统研究的专业人士、电网规划工程师、电动汽车行业从业者、能源政策制定者。 使用场景及目标:①评估电动汽车大规模接入对现有电网基础设施的压力;②优化电动汽车充电设施的布局和运营策略;③为相关政策和技术标准的制定提供科学依据。 其他说明:文中提供的Python代码片段用于辅助理解和验证理论分析,实际应用中需要更复杂的模型和详细的电网参数。
房地产 -【万科经典-第五园】第五园产品推介会.ppt
稳压器件.SchLib
1
模拟符号.SCHLIB
内容概要:本文详细介绍了如何在Simulink中构建并仿真三相电压型逆变器的SPWM调制和电压单闭环控制系统。首先,搭建了由六个IGBT组成的三相全桥逆变电路,并设置了LC滤波器和1000V直流电源。接着,利用PWM Generator模块生成SPWM波形,设置载波频率为2kHz,调制波为50Hz工频正弦波。为了实现精确的电压控制,采用了abc/dq变换将三相电压信号转换到旋转坐标系,并通过锁相环(PLL)进行同步角度跟踪。电压闭环控制使用了带有抗饱和处理的PI调节器,确保输出电压稳定。此外,文中还讨论了标幺值处理方法及其优势,以及如何通过FFT分析验证输出波形的质量。 适用人群:电力电子工程师、自动化控制专业学生、从事逆变器研究的技术人员。 使用场景及目标:适用于希望深入了解三相电压型逆变器控制原理和技术实现的研究人员和工程师。主要目标是掌握SPWM调制技术和电压单闭环控制的设计与调试方法,提高系统的稳定性和效率。 其他说明:文中提供了详细的建模步骤和参数设置指南,帮助读者快速上手并在实践中不断优化模型性能。同时,强调了一些常见的调试技巧和注意事项,如载波频率的选择、积分器防饱和处理等。
【蓝桥杯EDA】客观题解析
房地产 -物业 苏州设备房管理标准.ppt
3
房地产 -2024H1房地产市场总结与展望(新房篇).docx
内容概要:本文详细介绍了利用LabVIEW与PLC进行自动化数据交互的技术方案,涵盖参数管理、TCP通信、串口扫描、数据转移等方面。首先,通过配置文件(INI)实现参数的自动加载与保存,确保参数修改不影响程序运行。其次,在TCP通信方面采用异步模式和心跳包设计,增强通信稳定性,并加入CRC16校验避免数据丢失。对于串口扫描,则通过VISA配置实现状态触发,确保进出站检测的准确性。最后,针对不同类型的数据转移提出具体方法,如TDMS文件存储策略,确保高效可靠的数据处理。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是熟悉LabVIEW和PLC编程的从业者。 使用场景及目标:适用于需要将LabVIEW作为上位机与PLC进行数据交互的工业生产线环境,旨在提高系统的自动化程度、稳定性和易维护性。 其他说明:文中提供了多个实用代码片段和注意事项,帮助读者更好地理解和应用相关技术。
d65689da7ed20e21882a634f8f5ce6c9_faad2735d293907fb32f7c5837f7302a
内容概要:本文档《NISP&CISP考试题库.pdf》汇集了大量关于信息安全专业领域的练习题,涵盖风险评估、安全策略、访问控制、恶意代码防范、加密技术、安全模型等多个方面。文档通过选择题的形式探讨了信息安全保障、风险管理和技术实施等核心内容,强调了信息安全保障的动态性和持续性,以及信息安全管理体系(ISMS)的重要性。文档还详细介绍了多种安全技术和标准,如ISO27001、GB/T 22080、SSE-CMM、CC标准等,并通过具体案例和场景分析,帮助读者理解如何在实际环境中应用这些标准和技术。 适用人群:文档适用于信息安全领域的从业者,尤其是准备参加NISP(国家信息安全水平考试)和CISP(注册信息安全专业人员)认证考试的考生,以及从事信息安全管理工作、对信息安全有兴趣的技术人员。 使用场景及目标:①帮助考生系统复习信息安全领域的基础知识和技能,为考试做准备;②为企业内部信息安全培训提供参考资料;③加深信息安全从业人员对安全标准和技术的理解,提升其在实际工作中的应用能力;④帮助信息安全管理者了解如何构建和维护有效的信息安全管理体系。 其他说明:文档不仅提供了理论知识,还结合了实际案例,有助于读者理解信息安全的复杂性和多样性。文档强调了信息安全的多层次、多维度特性,指出信息安全不仅依赖于技术手段,还需要结合管理措施和人员培训。此外,文档中的题目设计贴近实际工作场景,能够有效提升读者应对信息安全挑战的能力。
3dmax插件K_Tools.v2.6
内容概要:“华中杯”是由华中地区高校或相关机构举办的数学建模竞赛,旨在培养学生的创新能力和团队合作精神。比赛主要面向全国高校在校生(以本科生为主,部分赛事允许研究生参加),采用团队赛形式(3人一组),参赛队伍需在72小时内完成建模、编程及论文写作。竞赛一般在每年4月或5月举行,设有多个奖项,具体比例根据参赛队伍数量确定。; 适合人群:对数学建模感兴趣并希望提升自身能力的全国高校在校生(本科生为主,部分赛事允许研究生参加)。; 使用场景及目标:①帮助学生了解数学建模竞赛的形式与流程;②为参赛者提供备赛建议,如学习往届真题、掌握Matlab、Python、LaTeX等工具以及明确团队分工;③鼓励学生关注官方通知,确保获取最新赛程和规则信息。; 其他说明:2025年的具体赛程、规则可能会有所调整,请以“华中杯数学建模竞赛官网”或主办方通知为准。可通过学校数学系或相关社团获取报名信息。