我以为我已经在AS3中找到了引用,但是下面的行为让我感到困惑:
// declarations for named individual reference later on
var myAmbientSound:Sound;
var myAmbientSoundLocation:String = "http://ambient_sound_location";
var myPeriodicSound:Sound;
var myPeriodicSoundLocation:String = "http://periodic_sound_location";
var myOccasionalSound:Sound;
var myOccasionalSoundLocation:String = "http://occasional_sound_location";
// for iterating through initialization routines
var mySoundArray:Array = [myAmbientSound, myPeriodicSound, myOccasionalSound];
var mySoundLocation:Array = [myAmbientSoundLocation, myPeriodicSoundLocation, myOccasionalSoundLocation];
// iterate through the array and initialize
for(var i:int = 0; i < mySoundArray.length; i++) {
mySoundArray[i] = new Sound();
mySoundArray[i].load(new URLRequest(mySoundLocation[i]));
}此时,我认为mySoundArray[0]将引用与myAmbientSound相同的对象;然而,访问myAmbientSound会抛出空指针异常,而mySoundArray[0]则按预期工作并引用Sound对象。我在这里误解了什么?
发布于 2010-02-17 22:44:51
它更像是java引用变量,而不是C指针。
var myAmbientSound:Sound;
var myPeriodicSound:Sound;
var myOccasionalSound:Sound;
//these variables are not initialized and hence contain null values现在创建一个包含这些变量的当前值(null)的数组
var mySoundArray:Array = [myAmbientSound, myPeriodicSound, myOccasionalSound];该数组现在包含三个空值[null, null, null],而不是您期望它包含的三个指向Sound对象的指针。
现在,当您调用mySoundArray[0] = new Sound();时,将创建一个新的Sound对象,并将其地址分配给数组的第一个位置-它不会修改myAmbientSound变量。
发布于 2010-02-18 04:58:43
由于其他人已经花时间提出了一些非常好的解释,所以我将尝试解决您隐含的问题:
在这一点上,我认为
mySoundArray[0]会引用与myAmbientSound相同的对象
但是myAmbiendSound没有引用任何东西。从你的代码中:
var myAmbientSound:Sound;上面只是创建了一个Sound类型的局部变量,一个潜在的引用。用外行术语来说,一个可以指向某物的“手指”。所有局部变量都是引用。顺便说一下,并非所有引用都是局部变量,对象属性也是引用,就像Array和Vector元素一样。无论如何,上面的表达式并没有创建Sound类的对象。它只声明了一个局部变量,可以引用Sound类的对象。在声明时,它有一个特殊的值undefined。
声明一个类似上面的变量和给它赋值是有区别的。Operator new创建一个对象并返回对该对象的引用。赋值运算符=的结果是引用左边的任何东西,大体上就是引用右边的东西。
让局部变量引用对象的一种方法是:
myAmbientSound = new Sound();然而,在您的示例中,正如我所说的,myAmbientSound变量有一个特殊的undefined值,因为您只是声明了它,并且还没有给它赋值。此外,正如我们从代码中看到的,在代码片段的整个运行时,它不会引用任何内容。
现在,在我用下面这行代码解释您最终要放入数组中的内容之前:
var mySoundArray:Array = [ myAmbientSound, ...,你必须记住数组元素,就像对象属性一样,也是引用--例如,像mySoundArray[1]一样,mySoundArray[0]可以引用一个对象,等等。
上面的代码行声明了一个新的局部变量,使其引用了一个新的数组对象。在一条语句中声明和定义。
现在,因为我们已经确定您的局部变量myAmbiendSound包含特殊的undefined值,所以您的第一个数组元素最终引用了相同的值- undefined,最初为。在稍后的循环中,您让第一个元素(或者,如果我们要谨慎一些,就是变量i引用的数量的元素)引用一个新的Sound对象。在这一点上(就像我们观察到的那样,对于整个代码段而言),由于myAmbiendSound是undefined,所以将两者进行相等比较将失败-它们不引用相同的对象,它们引用的对象也被视为“相等”( =如何在AS3中工作是另一个主题)-前者是undefined,而后者指向Sound对象。
此外,还有一个小更正:“访问”对象不会导致运行时异常。试图访问没有指向对象的引用的属性(使用点符号语法),但是会导致运行时异常。这就好像你写了trace(null.foo) - null不是一个对象,当然也没有名为foo的属性。undefined也是如此。
顺便说一下,null == undefined是true,而null === undefined是false。只是说说而已。在很少的情况下(当然,取决于),您将不得不遵守这一细节。
我希望这能把事情弄清楚。我认为这是对前面所说的所有内容的补充。
发布于 2010-02-17 23:07:26
通常,ActionScript、Java和其他语言中的引用与C/C++中的引用不同。如果引用像在C/C++中一样工作,那么您编写的代码将是正确的,并且可以按照您的预期工作。通常,您应该尝试将引用视为自动取消引用的指针。您的代码是C/C++引用和现代引用之间区别的一个很好的例子。
以下是此行为应用于垃圾收集器时的后果示例:
var someRef:Sound = new Sound();
someRef = null;那么我在第一行中创建的Sound对象仍然存在,并且可能会继续存在。记住这一点很重要,因为如果您在AS3中注册事件侦听器,则会创建一个对它们的额外引用,以防止它们被GC销毁。这就是为什么您几乎总是应该使用对AddEventListener的完整调用,强制它使用弱引用(GC不计入弱引用)。
此外,请记住,在AS3中,所有函数调用都是ByVal。所以这段代码不能工作:
function initSound(a:Sound, b:String):void {
a = new Sound();
a.load(new URLRequest(b);
}
var myAmbientSound:Sound;
var myAmbientSoundLocation:String = "http://ambient_sound_location";
initSound(myAmbientSound, myAmbientSoundLocation);好消息是,大多数具有内置垃圾收集的语言都有相同的引用行为,所以一旦掌握了它的诀窍,您就能够更快地掌握这些语言。
https://stackoverflow.com/questions/2281320
复制相似问题