.net 什么是托管C++;相当于C#using语句

.net 什么是托管C++;相当于C#using语句,.net,managed-c++,using-statement,.net,Managed C++,Using Statement,如何在托管C中编写以下C代码++ void Foo() { using (SqlConnection con = new SqlConnection("connectionStringGoesHere")) { //do stuff } } 澄清: 对于托管对象。如果您关心的是限制变量的生存期,而不是自动处理,则始终可以将其放入自己的范围: void Foo() { { SqlConnection con = new SqlCo

如何在托管C中编写以下C代码++

void Foo()
{
    using (SqlConnection con = new SqlConnection("connectionStringGoesHere"))
    {
         //do stuff
    }
}
澄清:
对于托管对象。

如果您关心的是限制变量的生存期,而不是自动处理,则始终可以将其放入自己的范围:

void Foo()
{
    {
        SqlConnection con = new SqlConnection("connectionStringGoesHere");
        // do stuff
        // delete it before end of scope of course!
    }
}

在托管C++中,只使用栈语义。

void Foo(){
   SqlConnection con("connectionStringGoesHere");
    //do stuff
}
当con超出范围时,将调用“析构函数”,即Dispose()。

假设您指的是C++/CLI(不是旧的托管C++),以下是您的选项:

(1) 通过使用自动/基于堆栈的对象模拟使用块:

{
  SqlConnection conn(connectionString);
}
这将在下一个封闭块结束时调用“conn”对象的析构函数。这是封闭函数还是手动添加到限制范围的块并不重要

(2) 显式调用“Dispose”,即销毁对象:

SqlConnection^ conn = nullptr;
try
{
  conn = gcnew SqlConnection(conntectionString);

}
finally
{
  if (conn != nullptr)
    delete conn;
}
第一种是直接取代“使用”。第二个选项是一个选项,通常您不需要这样做,除非您可以选择将引用传递到其他地方。

您可以在自动ptr样式中执行类似操作:

void foo()
{
    using( Foo, p, gcnew Foo() )
    {
        p->x = 100;
    }
}
以下是:

template <typename T>
public ref class using_auto_ptr
{
public:
    using_auto_ptr(T ^p) : m_p(p),m_use(1) {}
    ~using_auto_ptr() { delete m_p; }
    T^ operator -> () { return m_p; }
    int m_use;
private:
    T ^ m_p;
};

#define using(CLASS,VAR,ALLOC) \
    for ( using_auto_ptr<CLASS> VAR(ALLOC); VAR.m_use; --VAR.m_use)
#包括
使用名称空间std;
一次性类{
私人:
int=0;
公众:
int notDisposed(){
返回!处置;
}
void doDispose(){
这是真的;
处置();
}
虚拟void dispose(){}
};
类连接:公共一次性{
私人:
连接*previous=nullptr;
公众:
静态连接*实例;
连接(){
先前=实例;
实例=此;
}
无效处置(){
删除实例;
实例=先前的;
}
};
Connection*Connection::instance=nullptr;
#为(一次性*uu tmpPtr=obj;uu tmpPtr->notDisposed();u tmpPtr->doDispose())定义使用(obj)
int执行(常量字符*查询){
if(Connection::instance==nullptr){

难道这既不会调用作用域末尾的析构函数,也不会调用“Dispose()”。从这个意义上讲,它与C#中的效果相同。是的,你是正确的。不会。我假设这将在“do stuff”部分完成。我所指出的是,在新作用域之外无法访问con。第一个语法是什么(使用裸花括号限制作用域)即使通过抛出异常离开作用域,也保证调用Dispose?我不认为是这样,但当然我可能错了。是的,这是有保证的。确实,这就是这里的想法。当封闭作用域结束时,会调用堆栈分配对象的析构函数(通过异常定期或提前)-实际上,这与托管与否无关。在本机代码中也是如此。@Christian.K,您确定“除非您选择将引用传递到其他地方”?我认为该示例(1)即使在这种情况下也可以。需要注意的是,当var超出范围时,它会排队等待GC,但实际的GC可能“稍后”发生。因此,如果在失去作用域之前进行清理很重要,那么您应该显式地执行清理,而不是等待析构函数/终结器。最近我有一个这样的例子,我正在写入文件流,但没有显式地调用stream.Close()。我发现流直到“稍后某个时间”才完全刷新(即,当GC运行时)这导致了问题。解决方法是在流超出范围之前添加对stream.Close()的显式调用。@dlchambers我在这里没有实际经验,但在C++/CLI中有经验。也就是说,当调用析构函数时,实际上调用的是
Dispose
。因此,如果您有一个“正确”的类型实现
IDisposable
您应该很好。也就是说,实际GC的时间与
Dispose
本身无关,因为实际清理(确定性)发生在您预期的代码点(“var超出范围”)。
public ref class Foo
{
public:
    Foo() : x(0) {}
    ~Foo()
    {
    }
    int x;
};
#include <iostream>

using namespace std;


class Disposable{
private:
    int disposed=0;
public:
    int notDisposed(){
        return !disposed;
    }

    void doDispose(){
        disposed = true;
        dispose();
    }

    virtual void dispose(){}

};



class Connection : public Disposable {

private:
    Connection *previous=nullptr;
public:
    static Connection *instance;

    Connection(){
        previous=instance;
        instance=this;
    }

    void dispose(){
        delete instance;
        instance = previous;
    }
};

Connection *Connection::instance=nullptr;


#define using(obj) for(Disposable *__tmpPtr=obj;__tmpPtr->notDisposed();__tmpPtr->doDispose())

int Execute(const char* query){
    if(Connection::instance == nullptr){
        cout << "------- No Connection -------" << endl;
        cout << query << endl;
        cout << "------------------------------" << endl;
        cout << endl;

        return -1;//throw some Exception
    }

    cout << "------ Execution Result ------" << endl;
    cout << query << endl;
    cout << "------------------------------" << endl;
    cout << endl;

    return 0;
}

int main(int argc, const char * argv[]) {

    using(new Connection())
    {
        Execute("SELECT King FROM goats");//out of the scope
    }

    Execute("SELECT * FROM goats");//in the scope

}