具有非托管成员的托管类

具有非托管成员的托管类

问题描述:

我正在使用此类:

public ref class x: public System::Windows::Forms::Form
{ 
     private: gcroot<std::string> name;
}

我遇到以下错误:

IntelliSense: a member of a managed class cannot be of a non-managed class type

我知道我可以使用 char * ,但是如果我使用很多 char * 我将不得不手动执行 delete [] ,否则某些堆损坏问题将增加



我已经被困了两天了



注意:我必须使用c ++,并且必须在c ++中使用UI

I know i can use char*, but if I use lots of char* i will have to manually do the delete[] or some heap corruption issues will rise

I've been stuck on this for two days now

note: I have to use c++ and have to use UI in c++

这是gcroot<>的错误用法,仅当您在非托管类中保留对托管对象的引用时,才需要使用它。

That's the wrong usage for gcroot<>, you only need that if you keep a reference to a managed object in an unmanaged class.

在这种情况下,您只需要声明它为 string * 。指针,您不能在托管类中存储字符串对象,编译器确信您将大开眼界。您会收到与现在完全相同的错误消息。

In this case you only need to declare it string*. A pointer, you cannot store an string object inside your managed class, the compiler is convinced that you are going to shoot your leg off. You'll get the exact same error message you got now.

当垃圾收集器压缩gc堆并移动Form对象时,可能会发生不好的事情。这会使指向字符串对象的任何外部非托管指针无效,而垃圾回收器无法更新该指针。例如,当您将对字符串的引用传递给非托管代码并且在非托管代码执行时发生GC时,可以生成此类指针。指针现在不再有效,并且非托管代码在读取垃圾或破坏GC堆时将失败。特别是后者的事故极难诊断。只需调用std :: string成员方法之一就足以调用此失败模式,该方法会生成 this 指针。

Really Bad Things can happen when the garbage collector compacts the gc heap and moves the Form object. That invalidates any external unmanaged pointer to the string object without the garbage collector being able to update that pointer. Such a pointer can for example be generated when you pass a reference to the string to unmanaged code and the GC happens while that unmanaged code is executing. The pointer is now no longer valid and the unmanaged code fails when it reads garbage or corrupts the GC heap. Especially the latter mishap is extremely hard to diagnose. Just calling one of the std::string member methods is enough to invoke this failure mode, that generates the this pointer.

对于实际上需要托管对象中的std :: string不同寻常的是,您始终总是首先选择 String ^ 。并仅在需要时(通常在调用本机代码时)生成std :: string。仅当动态创建std :: string极其昂贵时,才考虑以这种方式进行操作。如果这样做,则在构造函数中创建std :: string对象。并在析构函数和终结器中再次销毁它。正确使用Form类是很棘手的,因为它已经具有析构函数和终结器,强烈考虑创建一个存储字符串的辅助类。

It is very unusual to actually need an std::string in a managed object, you always choose String^ first. And generate the std::string only when needed, typically when you call native code. Only ever consider doing it your way if creating the std::string on-the-fly is exceedingly expensive. If you do then create the std::string object in the constructor. And destroy it again in both the destructor and the finalizer. Which is pretty tricky to get right for the Form class since it already has a destructor and finalizer, strongly consider creating a little helper class that stores the string.