2013-03-07 33 views
12

Mảng đặc biệt, @_, trong đó tất cả các đối số được truyền cho một hàm có mặt, thực sự là một bí danh đối với các đối số được truyền. Do đó, bất kỳ thay đổi nào chúng tôi thực hiện trực tiếp với mảng đặc biệt này @_ cũng sẽ phản ánh trong chính. Điều này rõ ràng.Perl: mảng đặc biệt @_ không thực sự là bí danh?

#!/usr/bin/perl 

use warnings; 
use strict; 

$\="\n"; 

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

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

Đối với chương trình trên, tôi mong đợi các tài liệu tham khảo của @arr@_ để trỏ đến cùng một vị trí vì nó là một bí danh. Nhưng nó không phải là như vậy.

On chạy trên:

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

Nếu họ đang trỏ đến 2 địa điểm khác nhau, làm thế nào những thay đổi được thực hiện trong @_ được phản ánh trong @arr?

Tôi có thấy điều gì đó sai không? Làm ơn cho lời khuyên.

+4

'@ _' không phải là bí danh cho bất kỳ điều gì. Đó không phải là những gì tài liệu nói. * Các phần tử * riêng lẻ của '@ _' là các bí danh. –

Trả lời

17

này có thể trả lời bạn câu hỏi:

use warnings; 
use strict; 

$\="\n"; 

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

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

Output

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

Như bạn thấy, lập luận cá nhân có cùng địa chỉ nhưng container là không giống nhau. Nếu bạn đẩy một mục vào @_ trong func thì @arr sẽ không thay đổi (vì vậy bạn có thể làm shift trong funct). Vì vậy, mỗi đối số là một bí danh và các phần tử mảng được chuyển thành các mục riêng lẻ. @_ chứa tất cả các mục được chuyển vào chương trình con. Nếu bạn muốn sửa đổi một đối số mảng, bạn cần phải vượt qua nó bằng cách tham chiếu.

+2

Cảm ơn bạn rất nhiều ... một số điều tốt đẹp hôm nay ... – Guru

11

@_ không phải là bí danh; các yếu tố của nó là.

Hãy nhớ rằng

func(@arr); 

cũng giống như

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

vì điều duy nhất mà có thể được chuyển tới một tiểu là một danh sách vô hướng, và một mảng để đánh giá một danh sách của nó các yếu tố trong ngữ cảnh danh sách.

Vì vậy, đó có nghĩa là

func(@arr); 

về cơ bản là giống như

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

Thay đổi các yếu tố của @_ sẽ thay đổi các yếu tố của @arr, nhưng thêm và loại bỏ các yếu tố của @_ sẽ không thay đổi kể từ khi @arr chúng là các mảng khác nhau.

>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

cảm ơn ikegami .... – Guru

+0

Ví dụ được cải thiện. – ikegami

Các vấn đề liên quan