首页 > 其他分享 >openfoam 智能指针探索

openfoam 智能指针探索

时间:2023-03-02 20:01:24浏览次数:42  
标签:tmp const autoPtr openfoam 智能 inline ptr 指针

前言

今天看到一个程序,用到了智能指针,

virtual tmp<volScalarField> rho() const;

借此机会把有关智能指针的知识体系重新梳理一遍


智能指针autoPtr的由来:

首先要说明智能指针本质上是模板类,是对原有指针的改进,相比更安全,
image
of中的智能指针autoPtr很像原有的auto_ptr,但不是对原有的封装,而是重新写了一遍
of对autoPtr的描述如下:

An auto-pointer similar to the STL auto_ptr but with automatic casting
to a reference to the type and with pointer allocation checking on access.

std::auto_ptr的定义大致如下:

template <typename _Tp>
class auto_ptr
{
private:
    _Tp *_M_ptr;

public:
    explicit auto_ptr(_Tp *__p = 0) throw();
    auto_ptr(auto_ptr &__a) throw();
    auto_ptr &operator=(auto_ptr &__a) throw();
    ~auto_ptr();

    _Tp &operator*() const throw();
    _Tp *operator->() const throw();

    _Tp *get() const throw();
    _Tp *release() throw();
    void reset(_Tp *__p = 0) throw();
};

再看咱of中的autoPtr是何其相似,但实现方法肯定各有千秋

template<class T>
class autoPtr
{
        mutable T* ptr_;
public:
    typedef T Type;
        inline explicit autoPtr(T* = nullptr);
        inline autoPtr(const autoPtr<T>&);
        inline autoPtr(const autoPtr<T>&, const bool reuse);
        inline ~autoPtr();

            inline bool empty() const;
            inline bool valid() const;
            inline T* ptr();
            inline void set(T*);
            inline void reset(T* = nullptr);
            inline void clear();

            inline T& operator()();
            inline const T& operator()() const;
            inline T& operator*();
            inline const T& operator*() const;
            inline operator const T&() const;
            inline T* operator->();
            inline const T* operator->() const;
            inline void operator=(T*);
            inline void operator=(const autoPtr<T>&);
};

在autoPtr中,我们也能看到在autoPtr中加了很多unique_ptr的元素,比如说reset(),

了解of中的智能指针的来源,那么为什么要用智能指针呢,他的应用场景是哪些,下次我们自己写的时候要什么时候用


为什么要用智能指针:

举个例子,比如说我们要实现插值算法,用matlab写,这很简单

result = function(input)

现在我们学习C++了,知道了可以传指针或引用,可以这样写

function(&result, input);

相比之下of更倾向于使用matlab的书写方式
因为简单
不仅是看起来简单,写起来也简单,可以更直观的表达想法
对于没接触过C或C++的人来说,不必了解引用左值右值等一系列知识
在of中写动量方程,

fvVectorMatrix UEqn
(
	fvm::ddt(rho, U)
	+ fvm::div(rhoPhi, U)
	+ turbulence->divDevRhoReff(rho, U)
);

首先这是个类fvVectorMatrix的构造函数,还是个拷贝构造
那这就需要类内部的重载以及函数返回类型都是fvVectorMatrix类
对于需要引入方程的人来说这样写很明显更直观更简单

但是C++作为效率最高的语言,引用这个概念的提出肯定有他的道理
我们一般说引用是什么,很多说是别名,实际上没有说到本质
引用的本质是指针常量,如果换C语言的写法是这样的

int* const rb = &a;

matlab以简单易用著称,但用过matlab的人都知道matlab的效率极低,
本科时候当时不会向量化编程,参加数学建模比赛跑一个循环,跑了整整24小时,笔记本散热也不大行,后来送修主板了
为什么matlab效率低,很关键的一点是matlab一直都是复制拷贝
C/C++指针传地址效率就高很多,况且C++引用的本质就是指针
在简单易用和效率之间,matlab选择了前者,C++选择了后者

openfoam是一个非常强大的张量计算程序,既不能舍弃易用性抬高门槛,又不能反复使用复制拷贝降低效率,稀疏矩阵那么大拷贝来拷贝去算一个程序跑好几年成本太高

openfoam使用智能指针解决了这个问题,看起来不难读懂又能保证效率,这也就回答了为什么要使用智能指针

再回到我们刚刚说的动量方程拷贝构造上,首先在书写方法上依旧是matlab的显式书写方法,但实际上是C++的隐式移动拷贝
可能现在依旧疑惑在哪里看到用指针了,可以打开fvm命名空间的内容

namespace fvm
 {
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 template<class Type>
 tmp<fvMatrix<Type>>
 d2dt2
 (
     const GeometricField<Type, fvPatchField, volMesh>& vf
 )
 {
     return fv::d2dt2Scheme<Type>::New
     (
         vf.mesh(),
         vf.mesh().d2dt2Scheme("d2dt2(" + vf.name() + ')')
     ).ref().fvmD2dt2(vf);//这里返回的可是fvMatrix<Type>类型指针
 }
 
 
 template<class Type>
 tmp<fvMatrix<Type>>
 d2dt2
 (
     const dimensionedScalar& rho,
     const GeometricField<Type, fvPatchField, volMesh>& vf
 )
 {
     return fv::d2dt2Scheme<Type>::New
     (
         vf.mesh(),
         vf.mesh().d2dt2Scheme("d2dt2(" + rho.name() + ',' + vf.name() + ')')
     ).ref().fvmD2dt2(rho, vf);
 }
 
 
 template<class Type>
 tmp<fvMatrix<Type>>
 d2dt2
 (
     const volScalarField& rho,
     const GeometricField<Type, fvPatchField, volMesh>& vf
 )
 {
     return fv::d2dt2Scheme<Type>::New
     (
         vf.mesh(),
         vf.mesh().d2dt2Scheme("d2dt2(" + rho.name() + ',' + vf.name() + ')')
     ).ref().fvmD2dt2(rho, vf);
 }
 
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 } // End namespace fvm

看到了嘛,随便一个遍布tmp智能指针,在指针赋值时就已经完成了类的初始化
但又因为只是指针,可以用显式的方法去写,只要保证返回类型相同即可

fvm += fvc::surfaceIntegrate
(
	faceFlux*tinterpScheme_().correction(vf)
);

表面上是大型矩阵相加减,实际上是智能指针这个地址在执行重载,极大的提升了效率

打个比方,这就像高启强要和赵立冬或孟德海商量一件事,赵这个级别的不方便出面,出面的都是龚开疆或王秘书这样的人,又能传达指示又不消耗大量资源,好处就是双方都留有余地

智能指针智能的点就在于不需要或者出问题的时候能自动销毁,打开相关析构函数

template<class T>
inline Foam::tmp<T>::~tmp()
{
    clear();
}
template<class T>
inline void Foam::tmp<T>::clear() const
{
    if (isTmp() && ptr_)
    {
        if (ptr_->unique())
        {
            delete ptr_;
            ptr_ = 0;
        }
        else
        {
            ptr_->operator--();
            ptr_ = 0;
        }
    }
}

tmp析构时对该智能指针进行了delete,

记得狂飙里调查组一来最先销毁的也是龚开疆这个智能指针,,,

这样openfoam无需g++ -o优化也能有很好的运行效率


autoPtr与tmp的使用场合与区别

在openfoam中,autoPtr是强引用类型智能指针,tmp是弱引用类型智能指针
那我们在什么时候使用autoPtr以及tmp呢

autoPtr多使用在transport models ,boundry conditions,discretization schemes,turbulenceModel,interpolation schemes,gradient schemes或fvOptions这种动态多态中,更适合析构频次高的地方,智能指针autoPtr能够自动析构,因而被广泛使用

autoPtr<incompressible::RASModel> turbulence
(
	incompressible::RASModel::New(U, phi, laminarTransport)
);

autoPtr一旦有所指向只能移动,不能复制,同名同类型只能指向一个对象

再说tmp,之前有博客说tmp类似shared_ptr,实际上tmp的自我介绍中并没有像autoPtr一样提及相关类auto_ptr,和shared_ptr也不是继承关系,但实现功能很接近

A class for managing temporary objects.

tmp的自我介绍中说是管理临时变量的类,这个介绍更像是我们日常做的副本,就像我现在做的博客,害怕自己忘做份笔记,日后翻看,当然这个博客的建立首先是自己做好了理解,因而类似的,tmp的构造需要autoPtr在前面已经做好了指定,tmp配合进行副本引用
tmp的销毁和shared_ptr一致,具体可以见shared_ptr


一起探索openfoam也是相当有趣的一件事,非常欢迎私信讨论
指正的价值要比打赏更重要,下面是个人联系方式,希望能结交到志同道合的朋友
image

标签:tmp,const,autoPtr,openfoam,智能,inline,ptr,指针
From: https://www.cnblogs.com/heloveHe/p/17171433.html

相关文章

  • 数组指针
    数组指针:本质是指针变量,保存的是数组的首地址例如:int(*p)[5]=NULL;数组首元素地址。例如:intarr[3]={10,20,30};  arr就是首元素地址(&arr[0]==arr),a......
  • “2023数据安全智能化中国行”活动-北京站盛大开幕
    2月27日,北京站“2023数据安全智能化中国行”活动在北京北辰洲际酒店圆满举办。活动以“以全新的技术推动数据安全治理体系落地”为主题,聚焦数据安全技术创新、数据安全趋势......
  • 探索边缘、人工智能和物联网的交集
    “数据是新的石油”,这句话出现在企业首席信息官的雷达上已有15年多了。从那时起,企业数据堆栈已经发展到支持复杂的商业智能任务。最近,在2022年12月,由于OpenAI的ChatGPT,我们......
  • 手把手教你使用LabVIEW人工智能视觉工具包快速实现图像读取与采集
    (文章目录)前言今天我们一起来使用LabVIEWAI视觉工具包快速实现图像的读取与颜色空间转换、从摄像头采集图像。工具包的安装与下载方法可见之前的两篇博客。一、工具包......
  • 04-Go字符串、指针、结构体
    1字符串packagemain//字符串funcmain(){varastring="helloworld"//1按索引取值,只能取,不能改fmt.Println(a[0])//104utf-8对照......
  • 使用C#和Selenium将鼠标指针(光标)移动到特定位置或元素
    使用C#和Selenium将鼠标指针(光标)移动到特定位置或元素 我使用Selenium和C#执行单击操作。我可以执行点击操作,但我不能将鼠标指针(光标)移动到特定坐标或特定元素上。Ac......
  • 数组元素的指针变量
    数组元素的指针变量和数组名(作为地址)等价  在使用中,[]就是*()的缩写 为啥arr==&arr[0]&arr[0]==&*(arr+0)==arr+0==arr指向......
  • AIGC背后的人工智能理论及应用
    随着人工智能技术的不断发展,越来越多的AI技术被应用到了各个领域。其中,AIGC(ArtificialIntelligenceGeneralChip)作为一种通用人工智能芯片,受到了广泛的关注。本文将从理论......
  • 智能前置仓(微仓)如何高效低成本迎合市场随意更换商品?
    我们不得不面对一个非常尴尬的事实,那就是,伏尔泰曾经说过,不经巨大的困难,不会有伟大的事业。这不禁令我们深思问题的关键究竟为何?满足消费者下单后最快速的一小时内甚至30分......
  • 比较含退格的字符串---双指针
    比较含退格的字符串给定s和t两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回true。#代表退格字符。注意:如果对空文本输入退格字符,文本继续为空......