2013-03-07 48 views
12

特殊數組@_(其中傳遞給函數的所有參數都存在)實際上是傳遞參數的別名。因此,我們直接對這個特殊數組進行的任何更改都會反映在主數據庫中。這很清楚。Perl:特殊數組@_不是真的別名嗎?

#!/usr/bin/perl 

use warnings; 
use strict; 

$\="\n"; 

sub func { 
     print \@_; 
     $_++ for(@_); 
} 

my @arr=(2..4); 
print \@arr; 
func(@arr); 
print "@arr"; 

對於上述方案,我期望的@arr@_基準指向相同的位置,因爲它是一個別名。但事實並非如此。

在運行上面:

ARRAY(0x1b644d0) 
ARRAY(0x1b644e0) 
3 4 5 

如果他們指向2個不同地點,如何在@_所做的改變@arr的反映?

我看到有什麼問題嗎?請指教。

+4

'@ _'不是任何東西的別名。這不是文檔所說的。 '@ _'的個別*元素*是別名。 – 2013-03-07 11:02:08

回答

17

這可能會回答你的問題:

use warnings; 
use strict; 

$\="\n"; 

sub func { 
     print \@_; 
     $_++ for(@_); 
     print \$_ for @_; 
} 

my @arr=(2..4); 
print \@arr; 
func(@arr); 
print "@arr"; 
print \$_ for @arr; 

輸出

ARRAY(0x17fcba0) 
ARRAY(0x1824288) 
SCALAR(0x17fcc48) 
SCALAR(0x18196f8) 
SCALAR(0x1819710) 
3 4 5 
SCALAR(0x17fcc48) 
SCALAR(0x18196f8) 
SCALAR(0x1819710) 

正如你看到的,個別參數有相同的地址,但該容器是不一樣的。如果您在func中將項目推入@_@arr將不會更改(因此您可以在funct中執行shift)。所以,每個參數都是一個別名,數組元素作爲單獨的項目傳遞。 @_包含傳遞給子例程的所有項目。如果你想修改一個數組參數,你需要通過引用來傳遞它。

+2

感謝很多perreal..learnt今天有些不錯的東西... – Guru 2013-03-07 05:11:14

11

@_不是別名;它的元素是。

記住

func(@arr); 

相同

func($arr[0], $arr[1], ...); 

,因爲這可以傳遞給子的唯一事情是標量的列表,以及一個數組的計算結果爲列表其列表上下文中的元素。

因此,這意味着

func(@arr); 

是基本相同

local @_; 
alias $_[0] = $arr[0]; 
alias $_[1] = $arr[1]; 
... 
&func; 

更改的@_元素會改變@arr元素,但添加和刪除的@_元件不會改變@arr因爲他們是不同的陣列。

>perl -E"@a=(4..6); sub { $_[0] = '!';  say @_; }->(@a); say @a;" 
!56 
!56 

>perl -E"@a=(4..6); sub { splice(@_,0,1,'!'); say @_; }->(@a); say @a;" 
!56 
456 
+0

謝謝ikegami .... – Guru 2013-03-07 05:52:02

+0

改進的例子。 – ikegami 2013-03-07 05:58:08