2017-11-29 12 views
3

나는 지나가는 채플 예를 찾고있다. 이 예제는 작동하지만 입력을 "반환"하기 때문에 나쁜 형식으로 보입니다. 이것은 메모리를 낭비합니까? 수업을 운영하기위한 명확한 방법이 있습니까?예배당은 언제 참조로 전달되며 상수로 전달됩니까?

class PowerPuffGirl { 
    var secretIngredients: [1..0] string; 
} 

var bubbles = new PowerPuffGirl(); 
bubbles.secretIngredients.push_back("sugar"); 
bubbles.secretIngredients.push_back("spice"); 
bubbles.secretIngredients.push_back("everything nice"); 

writeln(bubbles.secretIngredients); 

proc kickAss(b: PowerPuffGirl) { 
    b.secretIngredients.push_back("Chemical X"); 
    return b; 
} 

bubbles = kickAss(bubbles); 
writeln(bubbles.secretIngredients); 

그리고 출력

sugar spice everything nice 
sugar spice everything nice Chemical X 

거품을 수정하는 기능을 사용할 수있는 가장 효율적인 방법은 무엇인가를 생산?

답변

5

채플이 참조로 인수를 전달하는지 여부는 인수 인 텐트에 의해 제어 될 수 있습니다. 예를 들어, 정수는 보통 값으로 통과하지만 우리는 참조를 전달할 수 있습니다

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을 가리키고 있습니다.

더 이상 존재하지 않는 변수에 대한 참조를 반환하는 프로그램을 작성할 수는 있습니다. 컴파일러에는 해당 영역에 대한 검사가 포함되어 있지만 완전하지는 않습니다. 그 지역에서 개선이 이루어 지길 바랍니다.