2 miscrosoft net miscrosoft_net 于 2017.09.17 13:10 提问

关于C#压栈,压栈的类型是一个类的对象

static void Main(string[] args)
{
Stack stack = new Stack();
Class1 c=new Class1();
for (int i = 0; i < 10;i++ )
{
c.n = i;
stack.Push(c);
}
for (int i = 0; i < 10; i++)
{
Console.WriteLine(stack.Pop().n);
}
}
上面的代码输出的都是‘9’

            static void Main(string[] args)
    {
        Stack<Class1> stack = new Stack<Class1>();
        for (int i = 0; i < 10;i++ )
        {
            Class1 c = new Class1();
            c.n = i;
            stack.Push(c);
        }
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine(stack.Pop().n);
        }
    }
            这样把对象new在循环里,输出的就是正确的
            (其中Class1这个类里面就一句 public int n;)

            我不明白为什么是这样?求解答,谢谢了

3个回答

weixin_39521929
weixin_39521929   2017.09.17 20:27
已采纳
  1. Stack表示对象的简单后进先出 (LIFO) 非泛型集合
  2. Pop()删除并返回 Stack 顶部的对象。Push(Object)在 Stack 的顶部插入一个对象。Push的值是个object对象,所有类型的基类
  3. Stack 接受 null 作为有效值,并允许重复的元素。 你的第一种做法,重复的添加同一对象的引用,这个引用始终指向入栈时的同一对象 c,for循环每次都在修改这个对象的n值 第二种做法,添加的是不同对象的引用,这些对象的类型相同,成员结构相同,但属性值不同,所有它们不同。for循环每次都在创建新对象,每个对象的赋值不同。出栈时每个引用指向入栈时对应的一个对象c,所以访问到的值是不同的。 引用跟值,结构体都是在栈上,用完就被gc了,对象是在堆上,最少使用以及没有引用指向它也gc 加强值类型与引用类型的概念,加油少年~ 给你搬运个知识链接http://www.cnblogs.com/tonney/archive/2011/04/28/2032205.html
yidaimu
yidaimu   2017.09.17 14:17

这个问题的关键是:理解引用类型和值类型的区别。
你第一种写法:Class1是一个类,属于引用类型。每次压栈的都是其实同一个对象(都是Class1的一个实例c)。for循环只是修改了这个c.n的值。for循环结束后相当于你你把c这个对象压栈了10次,每次出栈的都是同一个c。
第二种写法:新建了10个Class1对象,每次压栈的都是一个新的Class1对象,c只是局部变量的名称(出栈过程中无法访问名称c)。自然每次对c的赋值都是对不同的对象。
所以第一种输出都是9,第二种是0-9。

fight_in_dl
fight_in_dl   Ds   Rxr 2017.09.17 14:10

第一段代码中,

            Class1 c = new Class1();  //只生成一个Class1类的对象 c
            for (int i = 0; i < 10; i++) //i 从0循环到9
            {
                c.n = i; //每次循环,对象c的n值等于i,这样循环结束时,c.n = 9
                stack.Push(c); //循环结束时,压了10个Class1类的对象进栈,它们的n值都为9
            }

第二段代码中

            for (int i = 0; i < 10; i++) //i 从0循环到9
            {
                Class1 c = new Class1(); //每次循环,生成一个新的Class1类的对象,共生成10个对象实例
                c.n = i; //每个对象的n值等于当次循环时的i值
                stack.Push(c); //循环结束时,压了10个Class1类的对象进栈,它们的n值各不相同
            } 

如果对您有帮助,请采纳答案好吗,谢谢!

fight_in_dl
fight_in_dl 第一段代码,相当于同一个c对象进栈10次。
10 个月之前 回复
navylover
navylover 总结就是: 第一段代码中压了10个相同的对象进栈,第二段代码中压了10个不同的对象进栈。
10 个月之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
C 程序局部变量压栈出栈的理解
写这篇总结的缘由仅仅出于巧合,五一前帮一位同学看51的程序,在查看汇编代码的时候(事实上我当时的汇编知识基本都还给了老师),无意中问起我“某个局部变量的声明怎么没有对应的汇编语句”,我没有答出来。当时也只是把它当做一种常识给记了下来,平时不论还是在DSP、16位的单片上还是PC平台上编写c程序,由于程序不是很复杂且芯片资源通常足够,因此很少会考虑内存分配、堆栈方面的内容。这几天在看《Linux
递归方法的压栈和出栈(个人理解)
1.常见的很容易理解的求阶层 package ee; import java.util.Scanner; public class Rucursive { int sum=1; public int compute(int n) { if(n==0) { return 1; } return sum=n*compute(--n); } public s
使用List集合实现 压栈 弹栈功能
直接上代码。。,如下是运行结果: 123 小黄 Tue Jul 04 20:05:46 CST 2017 小明 package com.raylu.test; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.junit.Test; /**
C++ 简单实现压栈出栈
/********************************************************************** * Copyright (c)2015,WK Studios * Filename: stack.h * Compiler: GCC,VS,VC6.0 win32 * Author:WK * Time: 2015 3 29
C语言函数调用参数压栈顺序
很多人都知道,函数调用中,函数的参数是通过压栈出栈传递的。下面通过代码来验证压栈过程。 代码分两部分,参考了其他作者的代码后修改的。 1. 首先验证操作系统的栈的增长方向; 2. 汇编语言将参数压栈,然后调用C语言的函数。 代码1: 函数的临时变量从栈中分配内存,而static变量只初始化一次。利用这两个基本原理验证堆栈增长方向。 代码如下: #include in
汇编 压栈出栈
一 PS:EBP是当前函数的存取指针,即存储或者读取数时的指针基地址;ESP就是当前函数的栈顶指针。每一次发生函数的调用(主函数调用子函数)时,在被调用函数初始时,都会把当前函数(主函数)的EBP压栈,以便从子函数返回到主函数时可以获取EBP。 下面是按调用约定__stdcall 调用函数test(int p1,int p2)的汇编代码 假设执行函数前堆栈指针ESP为0xAAAA
C语言函数参数压栈顺序为何是从右到左?
要回答这个问题,就不得不谈一谈printf()函数,printf函数的原型是:printf(const char* format,…) 没错,它是一个不定参函数,那么我们在实际使用中是怎么样知道它的参数个数呢?这就要靠format了,编译器通过format中的%占位符的个数来确定参数的个数。
堆栈在内存中的压栈和弹栈工作原理
转载自http://blog.csdn.net/eastonwoo/article/details/8763216 堆栈在内存中的压栈和弹栈工作原理 一.概述:      网上关于堆栈的文章很多,但多为不祥尽.趁清明假期整理验证下.VC编译,XP平台. 调用函数入栈过程分以下5步: 1.压参数(右向左)-->2.压调用完函数后的第一条汇编指令-->3.保存本函数的栈顶地
函数参数的压栈过程
1 _cdecl    按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于“C”函数或者变量,修饰名是在函数名前加下划线。对于“C++”函数,有所不同。如函数void test(void)的修饰名是_test;对于不属于一个类的“C++”全局函数,修饰名是?test@@ZAXXZ。           这是MFC缺省调用约定。由于是调用者负责把参数弹出栈,所以可以给函数定义个数不定的参数,如
java之栈的压入和弹出
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不等。例如序列1、2、3、4、5是某栈的压栈序列,序列4、5、3、2、1是该压栈序列对应的一个弹出序列,但4、3、5、1、2就不是该压栈序列的弹出序列。 分析:如果下一个弹出的数字刚好是栈顶数字,那么直接弹出。如果下一个弹出的数字不是栈顶,我们把压入序列中没有入栈的数字压入到辅助栈,直