2013-07-19 81 views
1

我知道值类没有默认构造函数,因为编译器用零初始化此类中的所有元素。但是数组在值类不被初始化:值类中的CLI数组初始化

value class c_LocationVal 
{ 
public: 
    double x, y, z; 
    c_LocationVal(double i_x, double i_y, double i_z) {x = i_x; y = i_y; z = i_z;} 
}; 

typedef cli::array<c_LocationVal> arrloc; 

value class c_Managed 
{ 
public: 
    arrloc^ m_alocTest; 

    //c_Managed() { m_alocTest = gcnew arrloc(3); } --> not permitted 

    double funcManaged() 
    { 
    return m_alocTest[0].x; --> error: Object reference not set to an instance of an object 
    } 
}; 

我能欺骗和利用:

c_Managed(int i) { m_alocTest = gcnew arrloc(3); } 

但必须有另一种解决方案。
有人可以告诉我如何解决这个问题吗?

+0

C#中实际需要你称作弊。我假设C++/CLI的规则是一样的。难道你不能声明'c_LocationVal'的C数组吗? – leppie

+0

不幸的是,我不能:当我创建一个托管类型的C数组时,我将得到编译器错误C2728,并且当我在托管类型内创建一个非托管类型的数组时,我将得到编译器错误C4368。而且因为主应用程序是一个CLR-Winform,我不能使用非托管数组。 –

+0

[我如何在C++/CLI中指定一个固定大小的缓冲区?](http://stackoverflow.com/questions/2138473/how-do-i-specify-a-fixed-size-buffer-in -c-cli) –

回答

1

值类总是用“null/0”初始化。因此,值类中的托管引用也将始终初始化为“null”。如果你想有一个特殊的初始化,那么你只有解决方案,你指出:你需要创建一个特殊的构造函数,它有一些参数来正确地初始化值类。

问题是:你真的需要一个包含管理参考的值类吗?通常这也应该是ref class

另外,如果值类被复制会发生什么?参考文献应该如何处理?它也将直接复制!这是打算?价值课的目标是提供一个“真正的”副本!在你的情况下,它不会“完全复制” ......

普莱斯重新思考,如果value class是您的数据存储的最佳解决方案......

+0

当引用位于'value class'内时,增加了有关复制问题的注释... –

+0

因此,因为数组是一个引用类型,所以我不应该在值类中使用它?数组引用被复制,但不是数组内容?这是有道理的。我现在真的该开始这个周末了。 ;-) –

+0

如果他将数组直接嵌入到值类中,而不是引用,它将具有他要查找的值语义复制语义。 –

0

开关公共领域的财产,并做懒在检索属性时进行初始化。

value class c_Managed 
{ 
private: 
    arrloc^ m_alocTest; 

public: 
    arrloc^ AlocTest 
    { 
    arrloc^ get() 
    { 
     if(m_alocTest == nullptr) 
     { 
     msclr::lock(c_Managed::typeid) 
     if(m_alocTest == nullptr) 
      m_alocTest = gcnew arrloc(3); 
     } 

     return m_alocTest; 
    } 
    } 

    double funcManaged() 
    { 
    return AlocTest[0].x; 
    } 
}; 

为延迟初始化锁是不理想的,但它只是锁定唯一依靠的东西:this是值类型,所以锁定将框,并锁定将在包装盒上,不对象本身。因为它是一个值类型,所以提供任何引用类型作为字段来锁定会给出一个空引用,就像数组一样,所以这里没有帮助。我唯一能想到的就是这种类型的对象本身。

2

CLR只支持方法内的代码。编译器通过创建构造函数来模仿成员初始化表达式的行为(如有必要),并将表达式的代码移动到构造函数中。

这解释了为什么这是不允许的,你的表达式需要一个无参数的构造函数,并且这对于一个值类型来说是不合法的。

当然,你的伎俩将工作。但是一般来说,当你编写C++/CLI代码时,你需要略微调整C++的假设。 C++中的结构和类之间没有实际的区别。但是在托管代码中绝对不是这种情况。对于非常简单的类型,只能使用值类别。需要进行初始化时,会将选择重点放在ref class上。与具有数组的值类型一样,通常需要深层副本才能使其正常工作。不要害怕C++/CLI中的堆,它非常快。

+0

我只是想我可以避免通过使类成为值类型来实现复制构造函数或克隆方法。但是当你说价值类型只应该用于非常简单的结构以避免问题时,那么这是我的应用程序的错误类型,现在我真的需要处理ref类和clone方法。 –

+0

这是你必须调整的另一件事,3的规则在C++中很重要。它不在托管代码中,你只是从不写一个拷贝构造函数。垃圾回收器消除了需求。 –

+0

我现在再次遇到同样的问题。我需要一个值类的功能,但它必须包含一个小值类“c_LocationVal”的数组,因此我必须将上级类作为ref类。但那意味着我需要实现一种克隆方法,因此我不能像我想要的那样“调整”,或者有其他解决方案? –