在C++/CLI中创建某种类型的C++对象列表

5

我正在尝试在C++/CLI中创建一个C++对象的列表/集合,但是我已经尝试了各种方法,但似乎没有任何方法可行(编译时出现错误)。

我已经尝试过:

List<MyCppObject*> ^myList; //Does not allow non-.NET objects

ArrayList ^myList;
...
myList->Remove(myCppObject); //cannot convert parameter 1 from 'MyCppObject *' to 'System::Object ^'

我的要求:

1)列表必须包含C++对象。

2)我需要能够删除特定的对象(例如,vector无法满足需求,因为它只能从顶部进行push/pop操作)。

问题:如何在C++/CLI函数中创建一个包含C++对象的列表/集合,并且可以轻松地删除特定的对象?

如果需要其他信息,请告诉我;先感谢您的帮助!


1
调用 std::vector<T>::erase() 没有问题,但如果你经常这样做,它在性能方面并不是最优的。相反,std::list<T> 具有快速的任意位置插入/删除操作,并且不会使迭代器失效。 - Kerrek SB
@Kerrek SB & @Pete:不幸的是,std::vector 对我不起作用。我输入了 std::vector<MyCppObject*> myList; 并得到了以下错误:error C4368: cannot define 'myList' as a member of managed 'MyNamespace::MyManagedClass': mixed types are not supported. <sad face> - developer
@开发者:你从未提到过这是一个托管类型的数据成员。显然,知道这一点会很有用... ;-] - ildjarn
@Pete:std::list<T>::erase()是O(1)(通过迭代器),而list<T>::remove()是线性的(通过值)。比插入/删除复杂度更重要的是迭代器和引用的失效保证。但无论如何,本地和托管之间的混合似乎是一个更重要的问题! :) - Kerrek SB
@ildjarn:我没有意识到这是拼图中的重要一块。然而,显然我可以有一个指向我的本地类型的指针!因此,当我编译时不再出现错误。 :) http://www.codeproject.com/Messages/2204592/mixed-types-are-not-supported.aspx - developer
显示剩余2条评论
4个回答

3

要么使用System::IntPtr来处理非托管对象,例如List<System::IntPtr>^,或者使用std::list(或您自己的c++列表)并在其周围进行包装。

编辑:

您可以这样做

MyCppObject mynativeobj[10];
    System::Collections::Generic::List<System::IntPtr>^ mlist = gcnew System::Collections::Generic::List<System::IntPtr>();

    for(int i =0;i<10;i++)
    {
        mlist->Add(System::IntPtr((void*)&mynativeobj[i]));
    }

唯一的问题是所有的内存仍然驻留在非托管部分,所以如果您的变量超出作用域,IntPtr 就不再有效。而且您需要自己释放指针下的内存。

或者 std::set... 或者无序容器,可以是STL或其他像Google等的容器。 - user405725

2

要存储本地对象/指针,必须使用本地集合类。如果您希望集合类维护分配/释放,请使用 <MyCppObject>,或者如果您想保留内存分配(即集合类只保留指针),则使用 <MyCppObject*>

STL/CLR 类则相反 - 您可以使用 STL 类来存储 .NET 对象。


你会推荐哪些本地集合类呢?(类似于 .Net 中的 List) - developer
@developer: std::vector<> 是直接的本机等效于 System::Collections::Generic::List<> - ildjarn
1
显然我可以拥有指向本地类型的指针!因此我不再有错误。 :) http://www.codeproject.com/Messages/2204592/mixed-types-are-not-supported.aspx - developer

1

如果您不需要管理的容器,您可以使用原生的list类型:

#include <list>

std::list<MyCppObject*> mylist;
// ...
mylist.remove(mycppobjptr);

System::Collections::Generic::List 不是一个链表,它是一个可调整大小的数组。因此,std::vector<>std::list<> 更为推荐。 - ildjarn
然而,使用此代码我收到以下错误:错误 C4368:无法将'myList'定义为托管'MyNamespace::MyManagedClass'的成员:不支持混合类型。 - developer
@开发者:啊哈。我以为这只是一个本地变量。我猜这个答案对你来说没什么用了。:P - Ben Straub
显然我可以拥有指向本地类型的指针!因此我不再有错误。 :) http://www.codeproject.com/Messages/2204592/mixed-types-are-not-supported.aspx - developer

0

尝试

single object
MyCppObject^ _myCppObject = gcnew MyCppObject();

list of objects
List< MyCppObject ^>^ LIST = gcnew List< MyCppObject >();

add single element
LIST->Add( _myCppObject );

// remove single element
LIST->Remove( _myCppObject );

// these are all managed objects so when loss of scope it self destructs

// although such might be the case as per System::GC, you may still do...

LIST->Clear();

delete LIST;

LIST = nullptr;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接