채플이 참조로 인수를 전달하는지 여부는 인수 인 텐트에 의해 제어 될 수 있습니다. 예를 들어, 정수는 보통 값으로 통과하지만 우리는 참조를 전달할 수 있습니다
proc increment(ref x:int) { // 'ref' here is an argument intent
x += 1;
}
var x:int = 5;
increment(x);
writeln(x); // outputs 6
방법을 사용하면 인수가 기본 의도로 알려져 지정하지 않는 경우 유형이 전달하는. 채플은 레코드, 도메인 및 배열을 기본적으로 참조로 전달합니다. 그러나이 배열들 중 오직 배열은 함수 안에서 수정 가능합니다. (기록 및 도메인 const ref
통과 - 그들은 참조에 의해 전달되지만 그들이에 전달되는 기능을 수정할 수 있다는 것을 의미 배열은 함수가 그들과 함께 무엇에 따라 ref
또는 const ref
통과 -. array default intent 참조) .
이제 질문에 대한 클래스 인스턴스는 기본적으로 "값"으로 전달되지만 채플은 클래스 인스턴스의 "값"을 포인터로 간주합니다. 즉, 필드 (변형)가 변형되도록 허용하는 대신 클래스 인스턴스를 ref
으로 전달하면 클래스 인스턴스를 다른 클래스 인스턴스로 바꿀 수 있다는 의미입니다. 현재 클래스 인스턴스의 필드가 함수에서 수정 가능해서는 안된다고 말할 수있는 방법은 없습니다 (명시 적으로 변경할 수없는 데이터 유형이되도록하는 것 제외).
이 모든 것을 감안할 때 질문에서 제공 한 코드 샘플에서는 비효율적이지 않습니다. 특히, 여기에서 :
proc kickAss(b: PowerPuffGirl) {
b.secretIngredients.push_back("Chemical X");
return b;
}
인수는 인스턴스에 대한 포인터의 사본을 받게됩니다 b
을 수용하고 return b
는 포인터의 복사본을 반환합니다. 인스턴스의 내용 (특히 secretIngredients
배열)은 그 위치에 저장되어 남아 있으며 프로세스에서 복사되지 않습니다.
한 가지 더 :
이 예제는 작동하지만 내가 입력을 "반환"하고 있기 때문에 나쁜 형태처럼 보인다.
내가 말했듯이, 이것은 실제로 클래스 인스턴스 나 정수에서는 문제가되지 않습니다. 배열은 어떨까요? 이 예에서
proc identity(A) {
return A;
}
var A:[1..100] int;
writeln(identity(A));
,
identity()
에서
return A
실제로 어레이의 복사가 만들어 질
원인을한다. 어레이가 const ref
인 텐트로 전달 되었기 때문에 배열을 identity()
으로 전달할 때 해당 복사본이 만들어지지 않았습니다. 그러나이 함수는 참조 인 "값"을 반환하기 때문에 반환 할 때 복사해야합니다.언어 진화 문서에서 arrays return by value by default을 참조하십시오. proc refIdentity(ref arg) ref {
return arg;
}
var B:[1..10] int;
writeln(refIdentity(B));
지금의 카피가 없다 : 하나의 참조에 의해 배열을 반환하고자하는 경우 어떤 경우
은, 그것은 예를 들어하기는 ref
또는 const ref
반환 의도로 그렇게하는 것이 가능 배열과 모든 것은 단지 B
을 가리키고 있습니다. 더 이상 존재하지 않는 변수에 대한 참조를 반환하는 프로그램을 작성할 수는 있습니다. 컴파일러에는 해당 영역에 대한 검사가 포함되어 있지만 완전하지는 않습니다. 그 지역에서 개선이 이루어 지길 바랍니다.