:lvalue
하위에서 반환 된 스칼라는 복사되지 않습니다.
XS 하위에 의해 반환 된 스칼라는 복사되지 않습니다.
function (이름 지정된 연산자)에 의해 반환 된 스칼라는 복사되지 않습니다.
다른 하위에서 반환 된 스칼라가 복사됩니다.
하지만 과제가 시작되기 전에. 반환 된 값을 변수에 할당하면 해당 값을 복사하게됩니다 (일반 Perl 하위의 경우 다시).
즉 my $y = sub { $x }->();
사본 $x
을 두 번 의미합니다.
그러나 이는 최적화 때문에 중요하지 않습니다.
복사되지 않은 예부터 시작해 보겠습니다.
$ perl -le'
sub f :lvalue { my $x = 123; print \$x; $x }
my $r = \f();
print $r;
'
SCALAR(0x465eb48) # $x
SCALAR(0x465eb48) # The scalar on the stack
하지만 당신은 :lvalue
...
$ perl -le'
sub f { my $x = 123; print \$x; $x }
my $r = \f();
print $r;
'
SCALAR(0x17d0918) # $x
SCALAR(0x17b1ec0) # The scalar on the stack
더 나쁜, 하나는 보통 그래서 두 번째 복사본이 발생, 변수에 스칼라를 할당에 의해 다음 제거합니다.
$ perl -le'
sub f { my $x = 123; print \$x; $x }
my $r = \f(); # \
print $r; # > my $y = f();
my $y = $$r; #/
print \$y;
'
SCALAR(0x1802958) # $x
SCALAR(0x17e3eb0) # The scalar on the stack
SCALAR(0x18028f8) # $y
더하기 쪽에서는 문자열 복사 비용을 최소화하도록 최적화되어 있습니다.
XS 하위 및 함수 (명명 된 연산자)는 일반적으로 필사적 ("TEMP") 스칼라를 반환합니다. 이것들은 사형 선상에있는 스칼라들입니다. 그것들에 대한 참조를 요구하지 않으면 자동으로 파괴됩니다.
이전 버전의 Perl (< 5.20)에서는 필사적 문자열을 다른 스칼라에 할당하면 문자열 버퍼의 소유권이 이전되어 문자열 버퍼를 복사하지 않아도됩니다. 예를 들어 my $y = lc($x);
은 lc
으로 생성 된 문자열을 복사하지 않습니다. 단순히 문자열 포인터가 복사됩니다. 펄의 최신 버전 (≥ 5.20)에서
$ perl -MDevel::Peek -e'my $s = "abc"; Dump($s); $s = lc($s); Dump($s);'
SV = PV(0x1705840) at 0x1723768
REFCNT = 1
FLAGS = (PADMY,POK,IsCOW,pPOK)
PV = 0x172d4c0 "abc"\0
CUR = 3
LEN = 10
COW_REFCNT = 1
SV = PV(0x1705840) at 0x1723768
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x1730070 "abc"\0 <-- Note the change of address from stealing
CUR = 3 the buffer from the scalar returned by lc.
LEN = 10
, 할당 연산자 절대 [1] 복사 문자열 버퍼. 대신 최신 버전의 Perl은 COW (Copy-On-Write) 메커니즘을 사용합니다.
$ perl -MDevel::Peek -e'my $x = "abc"; my $y = $x; Dump($x); Dump($y);'
SV = PV(0x26b0530) at 0x26ce230
REFCNT = 1
FLAGS = (POK,IsCOW,pPOK)
PV = 0x26d68a0 "abc"\0 <----+
CUR = 3 |
LEN = 10 |
COW_REFCNT = 2 +-- Same buffer (0x26d68a0)
SV = PV(0x26b05c0) at 0x26ce248 |
REFCNT = 1 |
FLAGS = (POK,IsCOW,pPOK) |
PV = 0x26d68a0 "abc"\0 <----+
CUR = 3
LEN = 10
COW_REFCNT = 2
좋아 지금까지, 나는 스칼라에 대해 이야기했습니다. 자, 서브 및 함수는 스칼라 만 반환 할 수 있기 때문에 [2]입니다. 당신의 예에서
는 @return_value
에 할당 된 스칼라는 [3]가, 복사, 다음 과제로 @receiver
로 두 번째를 복사 반환됩니다.
배열에 대한 참조를 반환하면이 모든 현상을 피할 수 있습니다.
sub f { my @fizbobs = ...; \@fizbobs }
my $fizbobs = f();
유일하게 정의되지 않은 스칼라 인 참조가 복사됩니다.
좋아, 아마 결코. COW 수를 유지하려면 문자열 버퍼에 사용 가능한 바이트가 있어야한다고 생각합니다.
목록 컨텍스트에서 0 개 또는 1 개를 반환 할 수 있지만 스칼라 만 반환 할 수 있습니다.
마지막 하위 연산자는 목록 할당 연산자입니다. 목록 컨텍스트에서 목록 할당 연산자는 왼쪽 측면 (LHS)이 평가하는 스칼라를 반환합니다. 자세한 내용은 Scalar vs List Assignment Operator을 참조하십시오.
* "Perl 이외의 언어에 대해서는"return ""*'return'이 포함되어야합니다! 나는 그것이 서브 루틴의 마지막 문장에서 리턴 될리스트를 평가하는 것이 더 명확하고 (그리고 간략하게) 생각한다. 이전 perls에서는'return'을 추가하기 위해 작업 속도가 느려졌습니다.'return 1; 대신 모듈의 끝에'1;'을 넣으면됩니다. – Borodin
'perl (6th) p. 어떤 프로그래머들은 반환 값이있을 때마다 반환 값을 사용하는 것을 반환 값이라고 문서화하는 수단으로 사용하기를 좋아합니다. 당신은 정말로 그것을 필요로하지 않지만, 아무 것도 아프지 않습니다. 그러나 많은 펄 프로그래머들은 단지 7 글자의 타이핑이라고 생각합니다. _ :) 나는 펄 책을 좋아합니다. :) – jm666