Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ cli C+中的RAII+/CLI 我习惯了C++的RAI设施,我想在C++和CLI中使用RIIE和托管代码。他们都告诉我这是最好的做法_C++ Cli_Smart Pointers - Fatal编程技术网

C++ cli C+中的RAII+/CLI 我习惯了C++的RAI设施,我想在C++和CLI中使用RIIE和托管代码。他们都告诉我这是最好的做法

C++ cli C+中的RAII+/CLI 我习惯了C++的RAI设施,我想在C++和CLI中使用RIIE和托管代码。他们都告诉我这是最好的做法,c++-cli,smart-pointers,C++ Cli,Smart Pointers,我有这样的想法: ref struct Managed { // No default constructor Managed( /*...*/ ) { /*...*/ } ~Managed() { /* Important non-managed resource release here */ } // ... }; ref struct UsesManaged { Managed^ m_; array<Managed^

我有这样的想法:

ref struct Managed
{
    // No default constructor
    Managed( /*...*/ ) { /*...*/ }
    ~Managed() { /* Important non-managed resource release here */ }
    // ...
};

ref struct UsesManaged
{
    Managed^         m_;
    array<Managed^>^ a_;

    UsesManaged( Managed^ m, array<Managed^>^ a ) : m_(m), a_(a) {}
    // ...
};

ref struct Creator
{
    Managed^         m_;
    array<Managed^>^ a_;
    UsesManaged^     u_;

    Creator()
    {
        // Must allocate dynamically here, not in initializer list
        // because in my real code, I use "this" here for a callback.
        m_      = gcnew Managed( /*...*/ );
        a_      = gcnew array<Managed^>( 2 );
        a_[ 0 ] = gcnew Managed( /*...*/ );
        a_[ 1 ] = gcnew Managed( /*...*/ );
        u_      = gcnew UsesManaged( m_, a_ );
    }
};
ref结构管理
{
//没有默认构造函数
托管(/*…*/){/*…*/}
~Managed(){/*此处发布了重要的非托管资源*/}
// ...
};
ref struct UsesManaged
{
管理^m;
数组^a;
UsesManaged(托管^m,数组^a):m(m),a(a){
// ...
};
引用结构创建者
{
管理^m;
数组^a;
使用托管^u;
创建者()
{
//必须在此处动态分配,而不是在初始值设定项列表中
//因为在我的真实代码中,我在这里使用“this”作为回调。
m_u=gcnew Managed(/*…*/);
a=新阵列(2);
a_u0]=gcnew Managed(/*…*/);
a_u[1]=gcnew-Managed(/*…*/);
u_uu=gc管理的新用途(m_u,a_u);
}
};
我希望(1)自动销毁资源,这样我就不必手动删除每个新对象,尤其是在遇到异常时;(2) 安全、清晰地共享对象的能力(传递std::auto_ptr等不符合条件);(3)让VB或C#使用我的类,并在对象超出范围(例如,由于异常)时自动运行清理功能

标准C++中,我使用STD::SysDypPTR和STD::向量或类似的工具来自动化RAII。在这里,我可以使用STL/CLI的向量,但没有与之等效的共享ptr。我看到的唯一相关的C++/CLI智能指针是,它类似于std::auto_ptr,包括所有权转移语义,它与向量不兼容,尽管它们在数组中可以正常工作

要实现我的三个目标,正确的C++/CLI方法是什么?(另外请注意,我的主C++/CLI类(上面的Creator)将被VB/C#使用。)


[更新:在顶部添加了Herb Sutter和MS的链接,并添加了目标3(VB/C#的消费量)。]

您可以使用带有托管代码的RAII:如果您有此功能:

ref class A {
  ~A() { // implements/overrides the IDisposable::Dispose method
        // free managed and unmanaged resources here
   }
};
void foo()
{
  A a(cons_args); // stack-like usage
  // use a ...
}

然后您可以这样做:

ref class A {
  ~A() { // implements/overrides the IDisposable::Dispose method
        // free managed and unmanaged resources here
   }
};
void foo()
{
  A a(cons_args); // stack-like usage
  // use a ...
}
这将被有效地视为:

void foo()
{
  try
  {
     A^ a_ = gcnew A(cons_args);
  }
  finally
  {
     a_->~A();
  }
}

未测试,但这应该让您开始:

template<typename T>
value class counted_handle
{
    ref struct Count { int refCount; Count() : refCount(1) {} };
    T^ m_sharedHandle;
    Count^ m_sharedCount;

    void release() { if (m_sharedCount && 0 == --sharedCount->refCount) delete m_sharedHandle; m_sharedCount = nullptr; m_sharedHandle = nullptr; }
    void addref( if (m_sharedCount) ++m_sharedCount->refCount; }
public:
    counted_handle() : m_sharedHandle(nullptr), m_sharedCount(nullptr) {}
    counted_handle(T^ handle) : m_sharedHandle(handle), m_sharedCount(gcnew Count()) {}
    counted_handle(counted_handle<T>% src) : m_sharedHandle(src.m_sharedHandle), m_sharedCount(src.sharedCount) { addref(); }
    void ~counted_handle() { release(); }
    counted_handle<T>% operator=(counted_handle<T>% src) { src.addref(); release(); m_sharedHandle = src.m_sharedHandle; m_sharedCount = src.m_sharedCount; }
    counted_handle<T>% operator=(T^ handle) { release(); m_sharedHandle = handle; m_sharedCount = gcnew Count(); }
}
模板
值类\u句柄
{
ref结构计数{int refCount;Count():refCount(1){};
T^m_sharedHandle;
计数^m\u共享计数;
void release(){如果(m_sharedCount&&0==--sharedCount->refCount)删除m_sharedHandle;m_sharedCount=nullptr;m_sharedHandle=nullptr;}
void addref(如果(m_sharedCount)++m_sharedCount->refCount;}
公众:
counted_handle():m_sharedHandle(nullptr),m_sharedCount(nullptr){}
已计数的句柄(T^handle):m_sharedHandle(句柄),m_sharedCount(gcnew Count()){
计数句柄(计数句柄%src):m_sharedHandle(src.m_sharedHandle),m_sharedCount(src.sharedCount){addref();}
void~counted_handle(){release();}
计数的\u句柄%operator=(计数的\u句柄%src){src.addref();release();m_sharedHandle=src.m_sharedHandle;m_sharedCount=src.m_sharedCount;}
已计数的句柄%operator=(T^handle){release();m_sharedHandle=handle;m_sharedCount=gcnew Count();}
}

我认为我的问题的正确答案是由准答案对其他人答案的评论:

啊,你不能那样做。没有 强制垃圾收集器 摧毁一个物体。看到了吗 正确的方法是要求 一个明确的结束通话 在终结器中调用它。如果 客户机代码不可用的某些原因 清理,总承包商将(最终) 为您清理(在程序中) 终止协议(如果没有其他),但您 无法编写依赖于的代码 -比利·奥尼尔9月10日10点10分 16:02


除了他给出的链接,另请参见和。

+1,是的,这是一种方法。我非常不喜欢这种语法,它是一个主要的错误生成器,让新手几乎没有机会猜测他们何时必须使用插入符号。但就这样吧。+1--但我仍然认为任何人都需要正确阅读,但正如我在Creator's的评论中所暗示的那样s构造函数,我必须使用动态分配而不是“GC堆栈”分配。我真正需要的是一个相当于std::shared_ptr的C++/CLI。@mclimber:啊——你不能这么做。没有办法强迫垃圾收集器销毁对象。请看正确的方法,那就是要求显式关闭调用,并在终结器中对此进行调用。如果出于某种原因,客户端代码没有清理,GC将(最终)为您清理(在程序终止时,如果没有其他的东西),但是您不能编写依赖于C++的代码。@比利:您不能有确定性的解除分配,但可以有确定性的处理。当父对象被释放时(或对于本地对象,当作用域结束时),会自动调用。它肯定可以实现一个
自动句柄
变量(
计数句柄
?)它的行为类似于
std::shared_ptr
,但我认为Microsoft没有提供。严格来说,这不是RAII,因为您使用的是分配,而不是初始化来获得资源的所有权。它是一个智能指针,与RAII共享很多。IDisposable接口是托管代码中一个成熟的模式。但是您确实还必须包含终结器,以便自动释放资源。Add!Managed()。Hans,我想您可能已经删除了关于此问题的较长答案。这很有帮助,我希望您留下它,以便我们可以在那里讨论。