我知道值类没有默认构造函数,因为编译器会将此类中的所有元素初始化为零。但是值类中的数组未初始化:
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 :(得分:2)
CLR仅支持方法内部的代码。编译器通过在必要时创建构造函数并将表达式的代码移动到构造函数中来模拟成员初始化表达式的行为。
这解释了为什么不允许这样做,你的表达式需要一个无参数的构造函数,这对于值类型来说是不合法的。
当然,你的伎俩会奏效。但总的来说,在编写C ++ / CLI代码时,需要稍微调整C ++假设。在C ++中,struct和class之间没有实际的区别。但在托管代码中绝对不是这样。只对非常简单的类型使用值类。需要初始化会大大提示选择 ref class 。与具有数组的值类型一样,您通常需要深层复制才能使其无故障地工作。永远不要害怕C ++ / CLI中的堆,它非常快。
答案 1 :(得分:1)
值类始终使用“null / 0”初始化。因此,值类中的托管引用也将始终初始化为“null”。如果你想要一个特殊的初始化,那么你只有解决方案,你指出:你需要创建一个特殊的构造函数,它有一些参数来正确地“初始化”值类。
问题是:你真的需要一个包含托管引用的值类吗?通常情况下,这也应该是ref class
。
此外,如果复制了值类,会发生什么?参考会发生什么?它也会直接复制!这是有意的吗?价值类的目标是提供“真实”的副本!在你的情况下,它不会“完全复制”......
如果value class
是您数据存储的最佳解决方案,请重新考虑......
答案 2 :(得分: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
是一个值类型,因此锁定会将其锁定并且锁定在盒子上,而不是对象本身。因为它是一个值类型,所以提供任何引用类型作为要锁定的字段都会给出一个空引用,就像数组一样,所以没有任何帮助。我唯一可以想到的就是这种类型的类型对象本身。