1

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

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); }

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

4

3 回答 3

2

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

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

当然,你的伎俩会奏效。但一般来说,当您编写 C++/CLI 代码时,您需要稍微调整一下 C++ 假设。C++ 中的结构和类之间没有实际区别。但在托管代码中绝对不是这种情况。只对非常简单的类型使用值类。要求初始化严重提示了对ref 类的选择。与具有数组的值类型一样,您通常需要一个深层副本才能使其正常工作而不会发生意外。永远不要担心 C++/CLI 中的堆,它非常快。

于 2013-07-19T13:17:09.460 回答
1

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

问题是:你真的需要一个包含托管引用的值类吗???通常这也应该是一个ref class.

另外,如果值类被复制,会发生什么?参考应该发生什么?它也将直接复制!这是故意的吗?值类的目标是提供“真实”副本!在您的情况下,它不会“完全复制”...

请重新考虑是否value class是您数据存储的最佳解决方案...

于 2013-07-19T13:07:45.890 回答
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是一个值类型,所以锁定会将它装箱,并且锁会在盒子上,而不是在对象本身上。因为它是一个值类型,所以提供任何引用类型作为要锁定的字段都会给出一个空引用,就像数组一样,所以那里没有帮助。我能想到的唯一要锁定的是这种类型的类型对象本身。

于 2013-07-19T13:13:07.403 回答