无法理解为什么在分配后获得垃圾值

时间:2014-03-14 11:13:32

标签: windows visual-c++ c++-cli

我是C ++程序员。我对Windows编程很感兴趣,并试图在Windows窗体上使用visual c ++。但我遇到了很多问题。我现在面对的那个非常奇特,可以通过代码最好地描述。

表单中,我有两个变量:一个是 MyClass 列表,另一个是 MySettings 类型。

List<MyClass> NewClass;     // MyClass is value type
MySettings    NewSettings; // MySettings is value type

MySettings 包含 MyClass 的某些属性的值。我需要将这些值分配给 NewClass 的每个成员。所以我创建了一个名为 Init()的函数。在那里我尝试这样做 -

for (int i = 0; i < NewClass.Count; i++)
    {

                    /**
                    Checking the value of Cash
                    */

                    int temp = NewClass[i].GetCash(); // temp shows Garbage

                    /**
                    Setting the value of "Cash" in MyClass from NewSettings
                    */ 
                    NewClass[i].SetCash(NewSettings.GetCash());  // Cash is of type System::int32

                    /**
                    Now checking the Cash value after assignment
                    */

                    temp = NewClass[i].GetCash(); // temp shows exact same Garbage
    }

MyClass的定义 -

public value MyClass
{
private:

     // other variables
     String^ Name;
     int Cash;
     .
     .
     .

public:

     MyClass(String^ name)  // constructor
     {
         Name = name;
     }

     .
     .
     .

     int GetCash()
     {
         return Cash;
     }

public:     
     void SetCash(int amount)
     {
         Cash = amount;
     }
}

正如评论中提到的,即使在作业完成后,我也会获得现金的垃圾值。在调试模式下,它显示现金确实已更改为传递的值,但该值以某种方式释放。这是什么原因?如果我的编码错误,那么我该如何纠正呢?

更新

我编辑了构造函数,并将MyClass的每个int32属性(包括 Cash )设置为 0 )。现在temp每次都显示 0

2 个答案:

答案 0 :(得分:0)

...你确定List :: operator []实际上并没有返回列表中存储的对象的副本(复制consstructor)吗?在这种情况下,你是.setCash()复制的对象......

放一个

public value MyClass
{
   MyClass(const MyClass& a) { std::cout << "CC!" << std::endl; }
}

并找出

答案 1 :(得分:0)

根据您目前发布的代码,很难说出为什么&#34; temp&#34;的最终价值?是垃圾,因为它取决于&#34; NewSettings&#34;对象已初始化...如果你已正确初始化它,那么&#34; temp&#34;的最终值在你的&#34; for&#34;的每次迭代中循环应该很好地定义。但鉴于你的其余问题,我猜测它可能不是。

具体来说,你似乎很惊讶从你的初始&#34; NewClass [i] .GetCash()&#34;呼叫;我将重点关注其余部分,并希望您可以将其应用于确保NewSettings已正确初始化。

有三种基本方法可以正确初始化MyClass对象的Cash字段(因此没有垃圾值):

  1. 你可以有一个MyClass构造函数,在创建MyClass对象时初始化Cash字段(你不会在代码中显示一个)
  2. 您可能已经使用过,例如SetCash在使用之前设置它(也未在代码中显示)或
  3. 您可以以保证整数默认初始化的方式创建MyClass对象。
  4. 我猜你已经熟悉(1)和(2)并且想知道3,以及为什么事情必须&#34;正确初始化&#34;首先要避免垃圾价值。

    请注意,从C的早期开始,语言一直专注于让(可能是专家)程序员控制效率的细节,而不是提供合理的&#34;新手C程序员的行为。因此,例如,如果我们在函数中有一个局部变量,编译器必须生成代码来初始化它 - 这会导致程序稍微运行大多数架构都比较慢。所以,例如,如果你这样写:

    void example()
    {
        int i;
        printf("i is %d\n", i);
        i++;
        printf("i is now %d\n", i);
    }
    

    你可以为不同的电话获得不同的答案,因为用于&#34; i&#34;在函数的开头可能有不同的东西。尝试拨打&#34;示例&#34;在主函数中调用随机的其他东西(sqrt,printf,等等),看看你的系统做了什么。

    请注意,经常发现整数值最初为0,指针为空等,因为操作系统通常会在给出它们之前用0覆盖RAM中的旧值作为安全措施,您的计划。此功能内置于全局变量和静态变量的C和C ++语言定义中,因为它们通常直接进入操作系统新鲜的内存,而不是程序暂时使用的内存,可能已用于其他不再生活的变量。

    所以,你的&#34; temp的答案显示垃圾&#34;与如何创建NewClass中的MyClass对象有关...你可以阅读&#34; allocators&#34;在STL列表中,如果你喜欢;我自己也不了解细节。但是我怀疑你实际上并不关心&#34; temp&#34;的初始值,而是在测试过程中把它放在那里,并且实际上关心temp的 final 值,来自NewSettings。

    如果是这样的话,最简单的解决办法就是

    1. 为MySettings类提供构造函数,以确保NewSettings(以及所有其他MySetting对象)具有正确初始化的值以从GetCash返回,或
    2. 在进入代码中显示的循环之前,使用MySettings的其他一些方法为NewSettings 提供值。
    3. 如果您已经熟悉上述内容,并且可能已经初始化了NewSettings,那么问题可能是您的列表类更微妙的事情,正如其他响应者建议的那样...我原本误读了您的#34 ;列表&#34; class作为STL列表,但当我尝试使用[]下标STL列表时,它没有工作,所以我猜你有自己的列表类?如果是这样,你能澄清为什么你选择不使用标准列表类吗?