smart pointer是什么
In computer science, a smart pointer is an abstract data type that simulates a pointer while providing added features, such as automatic memory management or bounds checking.
是个抽象的数据类型,模拟指针的行为同时提供附加的features: 比如自动memory管理或边界检查
Such features are intended to reduce bugs caused by the misuse of pointers, while retaining efficiency. Smart pointers typically keep track of the memory they point to,
and may also be used to manage other resources, such as network connections and file handles. Smart pointers were first popularized in the programming language C++
during the first half of the 1990s as rebuttal to criticisms of C++'s lack of automatic garbage collection.
smart pointer用于减少指针误用引入的bug. smart pointer一般用于memory跟踪,也可用于管理其他资源如网络连接和文件句柄等。smart pointer 首先在c++中流行以用于反击对c++缺少自动垃圾回收。
Pointer misuse can be a major source of bugs. Smart pointers prevent most situations of memory leaks by making the memory deallocation automatic. More generally,
they make object destruction automatic: an object controlled by a smart pointer is automatically destroyed (finalized and then deallocated)
when the last (or only) owner of an object is destroyed, for example because the owner is a local variable, and execution leaves the variable's scope.
Smart pointers also eliminate pointers by postponing destruction until an object is no longer in use.
解决如下问题:1]防止内存泄露(一直不释放内存),2]当使用时内存已释放
If a language supports automatic garbage collection (for example, Java or C#), then smart pointers are unneeded for the reclaiming and safety aspects of memory management,
yet are useful for other purposes, such as cache data structure residence management and resource management of objects such as file handles or network sockets.
对支持自动垃圾回收的语言,smart pointer有什么用途?
smart pointer 类型
Several types of smart pointers exist. Some work with reference counting, others by assigning ownership of an object to one pointer.
利用引用计数(多个client去使用),控制执行对象的所有权
smart pointer的 C++实现
In C++, a smart pointer is implemented as a template class that mimics, by means of operator overloading, the behaviors of a traditional (raw) pointer, (e.g. dereferencing, assignment) while providing additional memory management features.
smart pointer 实现为模板类,通过运算符重载,模仿指针的行为如接引用,赋值等同时提供另外的内存管理功能
Smart pointers can facilitate intentional programming by expressing, in the type, how the memory of the referent of the pointer will be managed.
smart pointer能通过其类型表达怎样管理memory,如下面的例子
For example, if a C++ function returns a pointer, there is no way to know whether the caller should delete the memory of the referent
when the caller is finished with the information.
SomeType* AmbiguousFunction(); // What should be done with the result?
C++11 introduced a way to ensure correct memory management in this case by declaring the function to return a unique_ptr,std::unique_ptr<SomeType> ObviousFunction();
The declaration of the function return type as a unique_ptr makes explicit the fact that the caller takes ownership of the result, and the C++ runtime ensures that the memory will be reclaimed automatically.
unique_ptr
C++11 introduces std::unique_ptr, defined in the header <memory>
A unique_ptr is a container for a raw pointer, which the unique_ptr is said to own.
A unique_ptr explicitly prevents copying of its contained pointer (as would happen with normal assignment), but the std::move function can be used to transfer ownership of the contained pointer to another unique_ptr.
A unique_ptr cannot be copied because its copy constructor and assignment operators are explicitly deleted.
unique_ptr是raw pointer的容器,unique_ptr明确禁止了copy 操作,也就是只能由一个unique_ptr管理raw pointer, 但可以使用move操作转移所有权。
std::unique_ptr<int> p1(new int(5));
std::unique_ptr<int> p2 = p1; // Compile error.
std::unique_ptr<int> p3 = std::move(p1); // Transfers ownership. p3 now owns the memory and p1 is set to nullptr.
p3.reset(); // Deletes the memory.
p1.reset(); // Does nothing.
shared_ptr and weak_ptr
C++11 introduces std::shared_ptr and std::weak_ptr, defined in the header <memory>.
C++11 also introduces std::make_shared (std::make_unique was introduced in C++14) to safely allocate dynamic memory in the RAII paradigm.
A shared_ptr is a container for a raw pointer. It maintains reference counting ownership of its contained pointer in cooperation with all copies of the shared_ptr.
shared_ptr 维护引用计数,通过赋值shared_ptr增加引用计数。
An object referenced by the contained raw pointer will be destroyed when and only when all copies of the shared_ptr have been destroyed.
std::shared_ptr<int> p0(new int(5)); // Valid, allocates 1 integer and initialize it with value 5.
std::shared_ptr<int[]> p1(new int[5]); // Valid, allocates 5 integers.
std::shared_ptr<int[]> p2 = p1; // Both now own the memory.
p1.reset(); // Memory still exists, due to p2. reset()操作减少引用计数
p2.reset(); // Frees the memory, since no one else owns the memory.
怎样创建weak_ptr? It is created as a copy of a shared_ptr.
A weak_ptr is a container for a raw pointer. It is created as a copy of a shared_ptr.
The existence or destruction of weak_ptr copies of a shared_ptr have no effect on the shared_ptr or its other copies. (弱引用的创建或析构都不影响shared_ptr)
After all copies of a shared_ptr have been destroyed, all weak_ptr copies become empty.(当所有的shared_ptr引用都析构了,weak_ptr所有引用都变成了空)
std::shared_ptr<int> p1 = std::make_shared<int>(5);
std::weak_ptr<int> wp1 {p1}; // p1 owns the memory.
{
std::shared_ptr<int> p2 = wp1.lock(); // Now p1 and p2 own the memory.
// p2 is initialized from a weak pointer, so you have to check if the
// memory still exists!
if (p2) {
DoSomethingWith(p2);
}
}
// p2 is destroyed. Memory is owned by p1.
p1.reset(); // Free the memory.
std::shared_ptr<int> p3 = wp1.lock();
// Memory is gone, so we get an empty shared_ptr.
if (p3) { // code will not execute
ActionThatNeedsALivePointer(p3);
}
Dangling pointer and wild pointer
Dangling pointers and wild pointers in computer programming are pointers that do not point to a valid object of the appropriate type. These are special cases of memory safety violations.
悬空指针和野指针是没有指向有效对象的指针
Dangling pointer
Dangling pointers arise during object destruction, when an object that has an incoming reference is deleted or deallocated, without modifying the value of the pointer, so that the pointer still points to the memory location of the deallocated memory.
悬空指针发生在对象析构,但指向该对象的引用或指针的值没有被修改还是指向释放的地址
The system may reallocate the previously freed memory, and if the program then dereferences the (now) dangling pointer, unpredictable behavior may result, as the memory may now contain completely different data.
系统可能重新分配了释放的memory, 如果仍然使用原来的引用/指针(当前已经是悬空指针),会发生各种异常。
If the program writes to memory referenced by a dangling pointer, a silent corruption of unrelated data may result, leading to subtle bugs that can be extremely difficult to find.
如果是内存分配给另一个进程,linux发生段错误。
If the memory has been reallocated to another process, then attempting to dereference the dangling pointer can cause segmentation faults (UNIX, Linux) or general protection faults (Windows).
如果有足够的权限写任意地址,会导致系统稳定性
If the program has sufficient privileges to allow it to overwrite the bookkeeping data used by the kernel's memory allocator, the corruption can cause system instabilities.
有垃圾回收的语言,可以避免 dangling pointer
In object-oriented languages with garbage collection, dangling references are prevented by only destroying objects that are unreachable, meaning they do not have any incoming pointers; this is ensured either by tracing or reference counting.
Wild pointer
野指针说的是使用前没有被赋值
Wild pointers arise when a pointer is used prior to initialization to some known state, which is possible in some programming languages. They show the same erratic behavior as dangling pointers, though they are less likely to stay undetected because many compilers will raise a warning at compile time if declared variables are accessed before being initialized.
为什么需要弱引用?不会造成死锁?什么情景使用弱引用?
智能指针一个很重要的概念是“所有权”,所有权意味着当这个智能指针被销毁的时候,它指向的内存(或其它资源)也要一并销毁。这技术可以利用智能指针的生命周期,来自动地处理程序员自己分配的内存,避免显示地调用delete,是自动资源管理的一种重要实现方式。
为什么要引入“弱引用”指针呢?弱引用指针就是没有“所有权”的指针。有时候我只是想找个指向这块内存的指针,但我不想把这块内存的生命周期与这个指针关联。这种情况下,弱引用指针就代表“我指向这东西,但这东西什么时候释放不关我事儿……”
有些地方为了方便,直接用原始指针(raw pointer)来表示弱引用。然后用这种原始指针,其弱引用的含义不够明确,万一别人写个delete xxxx,你就被坑了……而且弱引用指针还有其它一些方便你正确使用它的好处。
cache use case 使用弱引用
For recently accessed objects, you want to keep them in memory, so you hold a strong pointer to them. Periodically, you scan the cache and decide which objects have not been accessed recently. You don't need to keep those in memory, so you get rid of the strong pointer.
But what if that object is in use and some other code holds a strong pointer to it? If the cache gets rid of its only pointer to the object, it can never find it again. So the cache keeps a weak pointer to objects that it needs to find if they happen to stay in memory.
This is exactly what a weak pointer does -- it allows you to locate an object if it's still around, but doesn't keep it around if nothing else needs it.
弱引用使用方法
std::shared_ptr<int> p1 = std::make_shared<int>(5);
std::weak_ptr<int> wp1 {p1}; // p1 owns the memory.
{
//升级为强引用,但可能失败,但一旦升级成功就得到了强引用
std::shared_ptr<int> p2 = wp1.lock(); // Now p1 and p2 own the memory.
// p2 is initialized from a weak pointer, so you have to check if the
// memory still exists!
if (p2) {
DoSomethingWith(p2);
}
}
Suppose you have Team
and Member
objects.
Obviously it's a relationship : the Team
object will have pointers to its Members
. And it's likely that the members will also have a back pointer to their Team
object.
Then you have a dependency cycle. If you use shared_ptr
, objects will no longer be automatically freed when you abandon reference on them, because they reference each other in a cyclic way. This is a memory leak.
You break this by using weak_ptr
. The "owner" typically use shared_ptr
and the "owned" use a weak_ptr
to its parent, and convert it temporarily to shared_ptr
when it needs access to its parent.(也就是上面说的弱引用使用方法)
Smart pointer 使用方法
Smart pointer 实现原理
// A generic smart pointer class
template
<
class
T>
class
SmartPtr {
T* ptr;
// Actual pointer
public
:
// Constructor
explicit
SmartPtr(T* p = NULL) { ptr = p; }
// Destructor
~SmartPtr() {
delete
(ptr); }
// Overloading dereferncing operator
T& operator*() {
return
*ptr; }
// Overloading arrow operator so that
// members of T can be accessed
// like a pointer (useful if T represents
// a class or struct or union type)
T* operator->() {
return
ptr; }
};
std::move()
C++11中std:move()的作用和用法_grf123的专栏-CSDN博客_c++ move()官方文档:http://www.cplusplus.com/reference/utility/move/?kw=move功能:返回传入参数的右值引用。右值引用的概念是在C++11才提出来的。在此之前只有一种引用。优点:调用此函数不会引起任何数据争用。(Calling this function introduces no data races.)看例子代码:// move ex...https://blog.csdn.net/grf123/article/details/105379337/move - C++ Referencehttp://www.cplusplus.com/reference/utility/move/?kw=move
//临时变量都 move到全局变量
std::vector<int> variables;
for (int i = 0; i < modified_subgraph->tensors_size(); ++i) {
auto* tensor = modified_subgraph->tensor(i);
if (tensor->is_variable) {
variables.push_back(i);
}
}
modified_subgraph->SetVariables(std::move(variables));
}
TfLiteStatus InterpreterBuilder::ApplyDelegates(Interpreter* interpreter,
int num_threads) {
// Apply Flex delegate if applicable.
if (has_flex_op_) {
if (auto flex_delegate = AcquireFlexDelegate()) {
return interpreter->ModifyGraphWithDelegate(std::move(flex_delegate));
}
}
return kTfLiteOk;
}
对象(smart pointer)建立在栈上,由作用域控制对象的生命周期,也就是自动调用析构函数
对象(smart pointer)建立在堆上,就要自动析构对象了