참조로 전달하는 것과 값으로 전달하는 것의 차이점은 무엇입니까?
차이점은 무엇입니까
- 참조로 전달 된 매개 변수
- 값으로 전달되는 매개 변수?
몇 가지 예를 들어 주시겠습니까?
무엇보다도 CS 이론에 정의 된 "값별 통과 대 기준 별 통과"구별은 이제 더 이상 사용되지 않습니다. 원래 "참조 별 통과"로 정의 된 기술이 선호도가 떨어지고 거의 사용 되지 않기 때문 입니다. 1
새로운 언어 2 는 다른 (그러나 유사한) 기술 쌍을 사용하여 혼동의 주요 원인 인 동일한 효과 (아래 참조) 를 달성하는 경향이 있습니다 .
이차적 인 혼란의 원천은 "참조에 의한 통과"에서 "참조"가 일반적인 용어 "참조"보다 더 좁은 의미를 갖는다 는 사실이다 (구가 선행하기 때문에).
이제 진정한 정의는 다음과 같습니다.
매개 변수가 reference 로 전달 되면 호출자와 수신자 는 매개 변수 에 동일한 변수 를 사용합니다 . 수신자가 매개 변수를 수정하면 효과가 발신자의 변수에 표시됩니다.
value 가 매개 변수를 전달 하면 호출자와 수신자는 동일한 값을 가진 두 개의 독립 변수 를 갖습니다. 수신자가 매개 변수를 수정하면 효과가 발신자에게 보이지 않습니다.
이 정의에서 참고할 사항은 다음과 같습니다.
여기서 "가변"은 호출자 (로컬 또는 글로벌) 변수 자체를 의미합니다. 즉, 로컬 변수를 참조로 전달하고 할당하면 호출자 변수 자체를 변경합니다. .
- 이것은 현재 나쁜 관행으로 간주됩니다 (내재적 종속성). 따라서 거의 모든 최신 언어는 독점적으로 또는 거의 독점적으로 가치에 따라 전달됩니다. 함수 별 참조는 이제 함수가 둘 이상의 값을 리턴 할 수없는 언어에서 주로 "출력 / 인수 인수"형식으로 사용됩니다.
"참조로 전달"에서 "참조"의 의미 . 일반적인 "참조"용어와의 차이점은 이 "참조"가 일시적이고 암시 적이라는 것입니다. 수신자가 기본적으로 얻는 것은 "가변"인데, 이는 원래와 같은 "변형"입니다. 이 효과가 달성되는 방식은 관련이 없습니다 (예 : 언어는 일부 구현 세부 사항 (주소, 포인터, 역 참조)을 모두 노출 할 수 있음). 이것은 모두 관련이 없습니다. 순 효과가 이것이라면 참조에 의한 것입니다.
이제 현대 언어에서 변수는 "참조 유형" ( "참조로 전달"이후에 발명되고 그에서 영감을 얻은 또 다른 개념) 인 경향이 있습니다 . 즉, 실제 객체 데이터는 어딘가에 (보통 힙에) 별도로 저장됩니다. 오직 "참조"만이 변수로 유지되고 매개 변수로 전달됩니다. 삼
변수의 값은 기술적으로 참조 된 개체가 아니라 참조 자체이기 때문에 이러한 참조를 전달하는 것은 값별 전달에 속합니다 . 그러나 프로그램에 대한 순 효과는 값별 또는 참조 별과 동일 할 수 있습니다.
- 호출자의 변수에서 참조를 가져와 인수로 전달한 경우 이는 참조 별 전달과 동일한 효과를 갖습니다. 참조 된 오브젝트가 수신자에서 변경되면 호출자에게 변경 사항이 표시됩니다.
- 그러나이 참조를 보유한 변수가 다시 확인되면 해당 개체를 가리키는 것이 중지 되므로이 변수에 대한 추가 작업은 현재 가리키는 모든 것에 영향을줍니다.
- 값별 전달과 동일한 효과를 얻기 위해 개체의 복사본이 어느 시점에 만들어집니다. 옵션은 다음과 같습니다.
- 발신자는 통화 전에 개인 사본을 만들고 대신 수신자에게 참조를 제공 할 수 있습니다.
- 일부 언어에서 일부 객체 유형은 "불변"입니다. 값을 변경하는 것처럼 보이는 조작은 실제로 원래 객체에 영향을주지 않고 완전히 새로운 객체를 만듭니다. 따라서 이러한 유형의 객체를 인수로 전달하면 항상 값을 전달하는 효과가 있습니다. 수신자의 변경 사항이있을 경우 언제든 변경이 필요한 경우 호출자의 사본이 자동으로 만들어지고 호출자의 오브젝트에는 영향을 미치지 않습니다.
- 기능적 언어에서 모든 객체는 변경할 수 없습니다.
보시다시피, 이 기술 쌍은 정의 수준의 기술과 거의 동일합니다. 단지 "변수"를 "참조 된 개체"로 바꾸십시오.
동의 된 이름이 없으므로 "값이 참조 인 경우 값별 호출"과 같은 왜곡 된 설명으로 이어집니다. 1975 년 Barbara Liskov는 " 객체 공유 "(또는 때때로 "공유") 라는 용어를 제안 하지는 않았습니다. 또한,이 문구들 중 어느 것도 원래 쌍과 평행을 이루지 않습니다. 과거의 용어가 더 나은 것이 없으면 다시 재사용되어 혼란을 초래 한 것도 당연합니다. 4
참고 : 오랫동안이 답변은 다음과 같이 말했습니다.
당신과 웹 페이지를 공유하고 싶다고 가정 해보십시오. URL을 말하면 참조로 전달됩니다. 해당 URL을 사용하여 볼 수있는 것과 동일한 웹 페이지를 볼 수 있습니다. 해당 페이지가 변경되면 둘 다 변경 사항을 볼 수 있습니다. URL을 삭제하면 해당 페이지에 대한 참조가 삭제되므로 실제 페이지 자체는 삭제되지 않습니다.
페이지를 인쇄하고 출력물을 제공하면 가치가 있습니다. 귀하의 페이지는 원본의 연결이 끊어졌습니다. 이후의 변경 사항은 표시되지 않으며 변경 내용 (예 : 인쇄물에 낙서)이 원본 페이지에 표시되지 않습니다. 출력물을 폐기하면 실제로 객체 사본을 폐기 한 것이지만 원래 웹 페이지는 그대로 유지됩니다.
이것은 "참조"의 더 좁은 의미를 제외하고 는 대부분 정확 합니다. 일시적이고 암시 적입니다 (필요하지는 않지만 명시 적 및 / 또는 지속적)는 추가 기능이며 참조 별 통과 의미의 일부가 아닙니다. 위에서 설명한대로). 더 가까운 비유는 문서의 사본을 제공하고 원본 작업을 권유하는 것입니다.
1 Fortran 또는 Visual Basic으로 프로그래밍하지 않는 한 기본 동작이 아니며 대부분의 현대 언어에서는 참조 기준 호출이 불가능합니다.
2 상당한 양의 노인도 그것을지지합니다
3 여러 현대 언어에서 모든 유형은 참조 유형입니다. 이 접근 방식은 1975 년 CLU 언어에 의해 개척되었으며 이후 Python 및 Ruby를 포함한 다른 많은 언어에서 채택되었습니다. 그리고 더 많은 언어가 하이브리드 접근 방식을 사용하는데, 일부 유형은 "값 유형"이고 다른 유형은 "참조 유형"입니다. 그 중 C #, Java 및 JavaScript가 있습니다.
4 오래된 용어 자체 를 재활용하는 것은 나쁘지 않지만 매번 어떤 의미가 사용되는지 분명하게 밝혀야합니다. 그렇게하지 않으면 정확히 혼란을 일으키는 원인이됩니다.
함수에 인수를 전달하는 방법입니다. 참조에 의한 전달은 호출 된 함수의 매개 변수가 호출자의 전달 된 인수 (값이 아니라 ID-변수 자체)와 동일 함을 의미합니다. 값으로 전달은 호출 된 함수의 매개 변수가 호출자의 전달 된 인수의 사본이됨을 의미합니다. 값은 같지만 변수 (ID)는 다릅니다. 따라서 어떤 경우에는 호출 된 함수가 수행 한 매개 변수를 변경하면 전달 된 인수가 변경되고 다른 경우에는 호출 된 함수 (복사본)의 매개 변수 값만 변경됩니다. 빨리 서둘러 :
- Java는 값별 전달 만 지원합니다. 객체에 대한 참조를 복사 할 때 호출 된 함수의 매개 변수가 동일한 객체를 가리키고 해당 객체의 변경 사항이 호출자에게 표시 되더라도 항상 인수를 복사합니다. 이것이 혼란 스러울 수 있으므로 여기 에 Jon Skeet이 말한 내용이 있습니다.
- C #은 값으로 전달 및 참조로 전달 (
ref
호출자 및 호출 된 함수에서 사용되는 키워드 )을 지원합니다. Jon Skeet도 여기에 대한 좋은 설명이 있습니다 . - C ++는 값으로 전달 및 참조로 전달 (호출 함수에서 사용되는 참조 매개 변수 유형)을 지원합니다. 이에 대한 설명은 다음과 같습니다.
코드
내 언어는 C ++이므로 여기서 사용하겠습니다.
// passes a pointer (called reference in java) to an integer
void call_by_value(int *p) { // :1
p = NULL;
}
// passes an integer
void call_by_value(int p) { // :2
p = 42;
}
// passes an integer by reference
void call_by_reference(int & p) { // :3
p = 42;
}
// this is the java style of passing references. NULL is called "null" there.
void call_by_value_special(int *p) { // :4
*p = 10; // changes what p points to ("what p references" in java)
// only changes the value of the parameter, but *not* of
// the argument passed by the caller. thus it's pass-by-value:
p = NULL;
}
int main() {
int value = 10;
int * pointer = &value;
call_by_value(pointer); // :1
assert(pointer == &value); // pointer was copied
call_by_value(value); // :2
assert(value == 10); // value was copied
call_by_reference(value); // :3
assert(value == 42); // value was passed by reference
call_by_value_special(pointer); // :4
// pointer was copied but what pointer references was changed.
assert(value == 10 && pointer == &value);
}
그리고 Java의 예는 아프지 않습니다.
class Example {
int value = 0;
// similar to :4 case in the c++ example
static void accept_reference(Example e) { // :1
e.value++; // will change the referenced object
e = null; // will only change the parameter
}
// similar to the :2 case in the c++ example
static void accept_primitive(int v) { // :2
v++; // will only change the parameter
}
public static void main(String... args) {
int value = 0;
Example ref = new Example(); // reference
// note what we pass is the reference, not the object. we can't
// pass objects. The reference is copied (pass-by-value).
accept_reference(ref); // :1
assert ref != null && ref.value == 1;
// the primitive int variable is copied
accept_primitive(value); // :2
assert value == 0;
}
}
위키 백과
http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_value
http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_reference
이 남자는 거의 그것을 못 박아 :
http://javadude.com/articles/passbyvalue.htm
여기에있는 많은 답변들 (특히 가장 많이 찬성 된 답변)은 "참조에 의한 호출"이 실제로 의미하는 바를 오해하기 때문에 사실 틀린 것입니다. 여기에 문제를 바로 잡으려는 시도가 있습니다.
TL; DR
가장 간단한 용어로 :
- 값으로 호출은 값 을 함수 인수로 전달 함을 의미합니다.
- 참조로 호출은 변수 를 함수 인수로 전달 함을 의미합니다.
은유 적 용어로 :
- 값에 의한 호출은 어디에 내가 당신에게 종이와 손 그것의 조각에 뭔가를 적어 . URL 일 수도 있고 전쟁과 평화의 완전한 사본 일 수도 있습니다. 그것이 무엇이든간에, 그것은 내가 당신에게 준 종이에 있습니다.그래서 이제는 사실상 당신의 종이 입니다. 이제 종이에 낙서를하거나 종이를 사용하여 다른 곳을 찾은 후 무엇이든 피킹 할 수 있습니다.
- 참고 로 전화 하면 내가 적어 놓은 노트를 줄 때입니다. 당신은 내 노트에 낙서를 할 수도 있고 (아마도 당신이 원하지 않을 수도 있습니다), 그 후에 나는 당신이 거기에 넣은 낙서와 함께 노트를 보관합니다. 또한, 당신이나 내가 쓴 것에 다른 곳을 찾는 방법에 대한 정보가 있다면, 당신이나 나는 그곳에 가서 그 정보를 가지고 바이올린을 칠 수 있습니다.
"값별 호출"및 "참조 별 호출" 이 의미 하지 않는 것은
이 두 개념은 참조 유형 개념 (자바에서는 모든 유형이 하위 유형이고 Object
C #에서는 모든 class
유형 임) 또는 C와 같은 포인터 유형 의 개념 (의미 적으로 동등 함 ) 과 완전히 독립적이며 직교한다는 점에 유의하십시오. 단순히 다른 구문으로 Java의 "참조 유형"을 참조하십시오.
참조 유형 의 개념은 URL에 해당합니다. 둘 다 정보 자체이며 다른 정보에 대한 참조 ( 포인터 인 경우)입니다. 여러 곳에 URL 사본을 여러 개 보유 할 수 있으며 링크 된 웹 사이트는 변경하지 않습니다. 웹 사이트가 업데이트되는 경우 모든 URL 사본은 여전히 업데이트 된 정보로 이어집니다. 반대로, 한 곳에서 URL을 변경해도 다른 URL 사본에는 영향을 미치지 않습니다.
참고 C ++은 "참조"(예를 들어,의 개념을 가지고 int&
있다) 하지 자바와 C #처럼 '의 "참조 유형"하지만 입니다 "참조에 의한 호출"처럼. Java 및 C #의 "참조 유형"및 Python의 모든 유형은 C 및 C ++에서 "포인터 유형"(예 :)을 호출하는 것과 같습니다 int*
.
여기 더 길고 공식적인 설명이 있습니다.
술어
우선, 몇 가지 중요한 용어를 강조하여 답변을 명확하게하고 단어를 사용할 때 모두 동일한 아이디어를 참조하도록하고 싶습니다. (실제로, 나는 이러한 주제에 대한 혼동의 대부분은 의도 된 의미를 완전히 전달하지 못하는 방식으로 단어를 사용하는 데 기인한다고 생각합니다.)
먼저 함수 선언의 C와 같은 언어로 된 예제가 있습니다.
void foo(int param) { // line 1
param += 1;
}
이 함수를 호출하는 예는 다음과 같습니다.
void bar() {
int arg = 1; // line 2
foo(arg); // line 3
}
이 예제를 사용하여 몇 가지 중요한 용어를 정의하려고합니다.
foo
A는 기능은 라인 1 (; C와 C 내가 여기에 가지 않을 선언과 정의 사이의 구별을 ++ 자바는 모든 기능의 방법을 주장하지만, 개념은 일반성의 손실없이 동일)에 선언param
A는 형식 매개 변수는 합니다foo
, 또한 라인 1에 선언arg
A는 변수 , 특히 로컬 변수 함수의bar
선언 라인에 초기화 2arg
또한 3 행 의 특정 호출 에 대한 논쟁 이기도합니다.foo
여기서 구별해야 할 두 가지 중요한 개념이 있습니다. 첫 번째는 값 과 변수입니다 .
- 값 은 IS 표현식 평가 결과 언어를. 예를 들어
bar
위 함수에서 line 뒤에int arg = 1;
표현식arg
의 값은1
입니다. - 변수 A는 값 용기 . 변수는 변경 가능 (이것은 대부분의 C와 유사한 언어에서 기본값 임), 읽기 전용 (예 : Java
final
또는 C #을 사용하여 선언readonly
) 또는 매우 불변 (예 : C ++ 사용const
) 일 수 있습니다.
구별해야 할 다른 중요한 개념 쌍은 매개 변수 와 인수입니다 .
- 파라미터 (도 불리는 형식 파라미터 ) A는 변수 의 함수 호출시에 호출자에 의해 공급되어야한다.
- 인수 A는 가치 함수의 호출에 의해 제공되는 기능의 특정 형식 인자를 만족
가치에 의한 전화
에서 값에 의한 호출 , 함수의 형식 매개 변수는 새로 함수 호출에 대해 생성되며, 이는이 초기화됩니다 변수 값 들이 인수는.
이것은 다른 종류의 변수가 값으로 초기화되는 것과 동일한 방식으로 작동합니다. 예를 들면 다음과 같습니다.
int arg = 1;
int another_variable = arg;
이곳까지 arg
와 another_variable
완전히 독립 변수 - 이들 값은 서로 독립적으로 변경할 수있다. 그러나 another_variable
선언 된 지점에서 arg
보유하고 있는 것과 동일한 값을 보유 하도록 초기화됩니다 1
.
이들은 독립 변수이므로 변경 사항 another_variable
은 영향을 미치지 않습니다 arg
.
int arg = 1;
int another_variable = arg;
another_variable = 2;
assert arg == 1; // true
assert another_variable == 2; // true
이것은 위의 예제 arg
와 의 관계와 정확히 동일 param
합니다. 대칭을 위해 여기에서 반복하겠습니다.
void foo(int param) {
param += 1;
}
void bar() {
int arg = 1;
foo(arg);
}
우리가 이런 식으로 코드를 작성한 것과 똑같습니다.
// entering function "bar" here
int arg = 1;
// entering function "foo" here
int param = arg;
param += 1;
// exiting function "foo" here
// exiting function "bar" here
즉, 어떤 정의하는 특성이다 값으로 호출 수단은 (상기 수신자이다 foo
이러한 경우)에 수신 된 값을 인수로되지만 자체 별도 갖는 변수 (발신자의 변수와 그 값을 bar
본 경우).
위의 은유로 돌아가서, 내가 bar
당신이라면 foo
, 내가 당신을 부를 때, 나는 당신에게 그 가치가 적힌 종이를 건네 줍니다. 그 종이라고 부릅니다 param
. 그 값은 내가 작성한 변수 (내 로컬 변수)에 쓴 값 의 사본 입니다 arg
.
(제외 : 하드웨어와 운영 체제에 따라, 한 함수에서 다른 함수를 호출하는 방법에 대한 다양한 호출 규칙이 있습니다. 호출 규칙은 우리가 종이에 값을 써서 당신에게 건네 주는지를 결정하는 것과 같습니다. , 또는 당신이 내가 쓴 종이가 있거나 우리 두 사람 앞에서 벽에 쓴다면, 이것은 흥미로운 주제이기도하지만이 긴 대답의 범위를 훨씬 넘어선 것입니다.)
참조로 전화
에서 참조로 호출 , 함수의 형식 매개 변수는 단순히 새 이름 같은 변수 인수로 해당 발신자 공급 장치는.
위의 예로 돌아가서 다음과 같습니다.
// entering function "bar" here
int arg = 1;
// entering function "foo" here
// aha! I note that "param" is just another name for "arg"
arg /* param */ += 1;
// exiting function "foo" here
// exiting function "bar" here
에 param
대한 또 다른 이름 일뿐 arg
입니다. 즉, 동일한 변수 이며 변경 사항 param
이 반영됩니다 arg
. 이는 참조 별 호출이 값별 호출과 다른 기본적인 방법입니다.
참조에 의한 호출을 지원하는 언어는 거의 없지만 C ++은 다음과 같이 할 수 있습니다.
void foo(int& param) {
param += 1;
}
void bar() {
int arg = 1;
foo(arg);
}
이 경우 param
와 같은 값 을 가지지 않고 arg
실제로 는 arg
다른 이름 으로 만 증가 하므로 bar
그 arg
값이 증가한 것을 관찰 할 수 있습니다 .
이것은 오늘날 Java, JavaScript, C, Objective-C, Python 또는 거의 모든 다른 인기있는 언어가 작동하는 방식 이 아닙니다 . 즉, 해당 언어는 참조로 호출 되지 않으며 값으로 호출됩니다.
부록 : 객체 공유에 의한 호출
값 으로 호출 하지만 실제 값이 참조 유형 또는 포인터 유형 인 경우 "값"자체는 그다지 흥미롭지 않습니다 (예 : C에서는 플랫폼 별 크기의 정수입니다). 그 가치가 가리키는 것은 흥미 롭습니다 .
해당 참조 유형 (즉, 포인터)이 가리키는 것이 변경 가능한 경우 흥미로운 효과가 있습니다. 포인팅 된 값을 수정할 수 있으며, 호출자가 관찰 할 수없는 경우에도 호출자는 지정된 값의 변경을 관찰 할 수 있습니다 포인터 자체로 변경됩니다.
URL의 비유를 다시 빌리기 위해, 우리가 웹 사이트에 URL 사본 을 제공했다는 사실은 우리가 관심있는 것이 URL이 아닌 웹 사이트라면 특히 흥미롭지 않습니다. URL 사본을 스크라이브해도 URL 사본에 영향을 미치지 않는다는 사실은 우리가 신경 쓰는 것이 아니며 실제로 Java 및 Python과 같은 언어에서는 "URL"또는 참조 유형 값이 전혀 수정되지 않으며, 지적한 것만 가능합니다).
Barbara Liskov는 CLU 프로그래밍 언어 (이 의미론을 가짐)를 발명 할 때 기존의 용어 "값별 호출"및 "참조 별 호출"이이 새로운 언어의 의미론을 설명하는 데 특히 유용하지 않다는 것을 깨달았습니다. 그래서 그녀는 새로운 용어 인 발명자에 의한 호출을 발명했습니다 .
기술적으로 가치에 의해 호출되는 언어를 논의 할 때 일반적으로 사용되는 유형이 참조 또는 포인터 유형 (즉, 거의 모든 현대식 명령형, 객체 지향 또는 다중 패러다임 프로그래밍 언어) 인 경우에, 나는 그것을 덜 혼란스럽게 생각합니다 단순히 값으로 전화 하거나 참조로 전화하는 것에 대해 이야기하지 마십시오 . 스틱하는 객체 공유로 전화 (또는 단순히 객체에 의해 호출 ) 아무도 혼동되지 않습니다. :-)
2 개 용어를 이해하기 전에 반드시 다음 사항을 이해합니다. 모든 물체에는 구별 할 수있는 두 가지가 있습니다.
- 그 가치.
- 주소입니다.
당신이 말하면 employee.name = "John"
약 2 일이 있다는 것을 알고있다 name
. 그 값 "John"
과 16 진 숫자 인 메모리에서의 위치는 다음과 같습니다 : 0x7fd5d258dd00
.
언어의 아키텍처 또는 객체 의 유형 (클래스, 구조체 등)에 따라 전송 "John"
중이거나0x7fd5d258dd00
합격 "John"
은 가치에 의한 통과라고합니다. 전달 0x7fd5d258dd00
은 참조로 전달하는 것으로 알려져 있습니다. 이 메모리 위치를 가리키는 사람은의 값에 액세스 할 수 있습니다 "John"
.
이에 대한 자세한 내용 은 포인터 역 참조에 대한 내용 과 클래스 (참조 유형)보다 구조체 (값 유형)를 선택하는 이유 를 읽어 보는 것이 좋습니다.
예를 들면 다음과 같습니다.
#include <iostream>
void by_val(int arg) { arg += 2; }
void by_ref(int&arg) { arg += 2; }
int main()
{
int x = 0;
by_val(x); std::cout << x << std::endl; // prints 0
by_ref(x); std::cout << x << std::endl; // prints 2
int y = 0;
by_ref(y); std::cout << y << std::endl; // prints 2
by_val(y); std::cout << y << std::endl; // prints 2
}
이것을 얻는 가장 간단한 방법은 Excel 파일입니다. 예를 들어 A1과 B1 셀에 5와 2라는 두 개의 숫자가 있고 세 번째 셀에서 합계를 찾고 싶다고 가정 해 봅시다. 두 가지 방법으로이 작업을 수행 할 수 있습니다.
이 셀에 = 5 + 2 를 입력하여 값을 셀 A2 에 전달합니다 . 이 경우 셀 A1 또는 B1의 값이 변경 되더라도 A2의 합은 동일하게 유지됩니다.
또는 = A1 + B1 을 입력 하여 셀 A1 및 B1의 "참조"를 셀 A2 에 전달합니다 . 이 경우 셀 A1 또는 B1의 값이 변경되면 A2의 합계도 변경됩니다.
ref로 전달하면 기본적으로 변수에 대한 포인터를 전달합니다. 변수의 사본을 전달하는 값으로 전달하십시오. 기본 사용법에서 이것은 일반적으로 ref에 의한 전달 변수 변경에 대한 호출 방법이며 호출되지 않는 값에 의한 전달을 의미합니다.
값으로 전달은 지정한 변수에 저장된 데이터의 COPY를 전송하고 참조로 전달은 변수 자체에 대한 직접 링크를 전송합니다. 따라서 참조로 변수를 전달한 다음 전달한 블록 내에서 변수를 변경하면 원래 변수가 변경됩니다. 단순히 값으로 전달하는 경우 원래 변수는 전달한 블록으로 변경할 수 없지만 호출시 포함 된 모든 사본을 얻을 수 있습니다.
값으로 전달-이 함수는 변수를 복사하고 사본과 함께 작동하므로 원래 변수의 내용은 변경되지 않습니다.
참조로 전달-함수는 원래 변수를 사용합니다. 다른 함수에서 변수를 변경하면 원래 변수도 변경됩니다.
예 (복사 및 사용 / 직접 시도하고 참조하십시오) :
#include <iostream>
using namespace std;
void funct1(int a){ //pass-by-value
a = 6; //now "a" is 6 only in funct1, but not in main or anywhere else
}
void funct2(int &a){ //pass-by-reference
a = 7; //now "a" is 7 both in funct2, main and everywhere else it'll be used
}
int main()
{
int a = 5;
funct1(a);
cout<<endl<<"A is currently "<<a<<endl<<endl; //will output 5
funct2(a);
cout<<endl<<"A is currently "<<a<<endl<<endl; //will output 7
return 0;
}
단순하게 유지하십시오. 텍스트의 벽은 나쁜 습관이 될 수 있습니다.
이들 사이의 주요 차이점은 값 유형 변수가 값을 저장한다는 점입니다. 따라서 메소드 호출에서 값 유형 변수를 지정하면 해당 변수 값의 사본이 메소드에 전달됩니다. 참조 유형 변수는 객체에 대한 참조를 저장하므로 참조 유형 변수를 인수로 지정하면 객체를 참조하는 실제 참조의 사본이 메소드에 전달됩니다. 참조 자체가 값으로 전달 되더라도 메소드는 수신 한 참조를 사용하여 원래 객체와 상호 작용하고 가능하면 수정할 수 있습니다. 유사하게, return 문을 통해 메소드로부터 정보를 리턴 할 때, 메소드는 값 유형 변수에 저장된 값의 사본 또는 참조 유형 변수에 저장된 참조의 사본을 리턴합니다. 참조가 리턴되면 호출 메소드는 해당 참조를 사용하여 참조 된 오브젝트와 상호 작용할 수 있습니다. 그래서,
C #에서는 호출 된 메서드가 변수를 수정할 수 있도록 참조로 변수를 전달하기 위해 C #은 키워드 ref 및 out을 제공합니다. ref 키워드를 매개 변수 선언에 적용하면 참조로 변수를 메서드에 전달할 수 있습니다. 호출 된 메서드는 호출자의 원래 변수를 수정할 수 있습니다. ref 키워드는 호출 메소드에서 이미 초기화 된 변수에 사용됩니다. 일반적으로 메소드 호출에 초기화되지 않은 변수가 인수로 포함되면 컴파일러에서 오류가 발생합니다. 키워드를 out으로하여 매개 변수를 선행하면 출력 매개 변수가 작성됩니다. 이것은 인수가 참조로 호출 된 메소드에 전달되고 호출 된 메소드가 호출자의 원래 변수에 값을 지정 함을 컴파일러에 표시합니다. 메소드가 가능한 모든 실행 경로에서 출력 매개 변수에 값을 지정하지 않으면 컴파일러가 오류를 생성합니다. 또한 컴파일러가 메소드에 인수로 전달 된 초기화되지 않은 변수에 대한 오류 메시지를 생성하지 못하게합니다. 메소드는 return 문을 통해 호출자에게 하나의 값만 리턴 할 수 있지만 여러 출력 (ref 및 / 또는 out) 매개 변수를 지정하여 많은 값을 리턴 할 수 있습니다.
C # 토론 및 예제를 참조하십시오 링크 텍스트
예 :
class Dog
{
public:
barkAt( const std::string& pOtherDog ); // const reference
barkAt( std::string pOtherDog ); // value
};
const &
일반적으로 최고입니다. 건설 및 파괴 페널티가 발생하지 않습니다. 참조가 구성되지 않은 경우 인터페이스는 전달 된 데이터를 변경하도록 제안합니다.
요컨대, 지나가는 값은 WHAT이며 참조는 지나는 곳입니다.
값이 VAR1 = "Happy Guy!"이면 "Happy Guy!"만 표시됩니다. VAR1이 "Happy Gal!"로 바뀌면 알 수 없습니다. 참조로 전달되고 VAR1이 변경되면 변경됩니다.
값으로 전달은 인수를 사용하여 값을 함수에 전달하는 방법을 의미합니다. 값으로 전달할 때 우리는 지정한 변수에 저장된 데이터를 복사하고 데이터를 복사 할 때 참조로 전달하는 것보다 느립니다. 우리는 복사 된 데이터를 변경하여 원본 데이터는 영향을받지 않습니다. nd 참조 또는 전달 주소로 변수 자체에 직접 링크를 보냅니다. 또는 변수에 포인터를 전달합니다. 그것은 더 적은 시간이 소비되는 bcse가 빠릅니다.
원래 변수의 값을 함수에 전달한 후 변경하지 않으려면 " pass by value "매개 변수를 사용 하여 함수를 구성해야합니다 .
그러면 함수는 값만 가지지 만 전달 된 변수의 주소는 갖지 않습니다. 변수의 주소가 없으면 함수 내부의 코드는 함수 외부에서 볼 때 변수 값을 변경할 수 없습니다.
그러나 함수 가 외부에서 볼 때 변수 값을 변경 하는 기능을 제공 하려면 pass by reference 를 사용해야 합니다. 값과 주소 (참조)가 모두 전달되어 함수 내에서 사용 가능합니다.
다음은 전달 값-포인터 값-참조 의 차이점을 보여주는 예입니다 .
void swap_by_value(int a, int b){
int temp;
temp = a;
a = b;
b = temp;
}
void swap_by_pointer(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void swap_by_reference(int &a, int &b){
int temp;
temp = a;
a = b;
b = temp;
}
int main(void){
int arg1 = 1, arg2 = 2;
swap_by_value(arg1, arg2);
cout << arg1 << " " << arg2 << endl; //prints 1 2
swap_by_pointer(&arg1, &arg2);
cout << arg1 << " " << arg2 << endl; //prints 2 1
arg1 = 1; //reset values
arg2 = 2;
swap_by_reference(arg1, arg2);
cout << arg1 << " " << arg2 << endl; //prints 2 1
}
"참조로 전달"방법에는 중요한 제한이 있습니다. 매개 변수가 참조 로 전달 된 것으로 선언되면 (& 기호가 앞에 옴) 해당 실제 매개 변수는 변수 여야합니다 .
"값에 의해 전달됨"형식 매개 변수를 참조하는 실제 매개 변수는 일반적으로 표현식 일 수 있으므로 변수뿐만 아니라 리터럴 또는 함수 호출 결과도 사용할 수 있습니다.
이 함수는 변수 이외의 다른 값에 값을 넣을 수 없습니다. 리터럴에 새로운 값을 할당하거나 표현식이 결과를 변경하도록 강요 할 수 없습니다.
추신 : 현재 스레드에서 Dylan Beattie 답변을 확인하여 일반 단어로 설명 할 수 있습니다.
'Programming' 카테고리의 다른 글
C ++ 코드 파일 확장자? (0) | 2020.02.10 |
---|---|
멀티 파트 / 폼 데이터 요청을 보내기위한 도구 (0) | 2020.02.10 |
Xamarin C # 및 Java로 작성된 Android 앱의 성능을 비교하는 벤치 마크 (코드 및 결과)가 있습니까? (0) | 2020.02.10 |
궁금한 null 병합 연산자 사용자 지정 암시 적 변환 동작 (0) | 2020.02.10 |
문자열을 목록으로 나누는 방법? (0) | 2020.02.10 |