C ++에서 참조로 통과하는 것에 대한 포인터를 통과 할 수있는 이점이 있습니까?

StackOverflow https://stackoverflow.com/questions/334856

문제

C ++에서 참조로 통과하는 것에 대한 포인터를 통과하면 어떤 이점이 있습니까?

최근에, 나는 참조별로 통과하는 대신 포인터에 의해 통과 된 기능 인수를 선택한 많은 예를 보았다. 이 작업을 수행하는 데 이점이 있습니까?

예시:

func(SPRITE *x);

전화로

func(&mySprite);

vs.

func(SPRITE &x);

전화로

func(mySprite);
도움이 되었습니까?

해결책

포인터는 널 매개 변수를 수신 할 수 있지만 참조 매개 변수는 할 수 없습니다. "객체 없음"을 통과 할 수있는 기회가 있다면 참조 대신 포인터를 사용하십시오.

또한 포인터를 통과하면 콜 사이트에서 객체가 값으로 전달되는지 또는 참조에 따라 명시 적으로 볼 수 있습니다.

// Is mySprite passed by value or by reference?  You can't tell 
// without looking at the definition of func()
func(mySprite);

// func2 passes "by pointer" - no need to look up function definition
func2(&mySprite);

다른 팁

포인터로지나갑니다

  • 발신자는 주소를 가져 가야합니다 -> 투명하지 않음
  • 0 값을 의미 할 수 있습니다 nothing. 이것은 선택적 인수를 제공하는 데 사용할 수 있습니다.

참조로 통과하십시오

  • 발신자는 객체를 통과합니다 -> 투명. 포인터 유형에 대한 과부하가 불가능하기 때문에 운영자 과부하에 사용해야합니다 (포인터는 제작 된 유형입니다). 그래서 당신은 할 수 없습니다 string s = &str1 + &str2; 포인터 사용.
  • NO 0 값 가능 -> 호출 함수를 확인할 필요가 없습니다.
  • Const에 대한 언급은 또한 임시를 받아들입니다. void f(const T& t); ... f(T(a, b, c));, Pointers는 임시 주소를 취할 수 없기 때문에 그렇게 사용할 수 없습니다.
  • 마지막으로, 참조는 사용하기 쉽습니다 -> 버그 가능성이 적습니다.

Allen Holub의 "발에 자신을 쏘기에 충분한 로프"는 다음 두 가지 규칙을 나열합니다.

120. Reference arguments should always be `const`
121. Never use references as outputs, use pointers

그는 참조가 C ++에 추가 된 몇 가지 이유를 나열합니다.

  • 사본 생성자를 정의하는 데 필요합니다
  • 운영자 과부하에 필요합니다
  • const 참조는 사본을 피하면서 통과 할 수있는 의미를 가질 수 있습니다.

그의 주요 요점은 통화 사이트에서 매개 변수가 참조인지 값 매개 변수인지 여부에 대한 표시가 없기 때문에 참조는 '출력'매개 변수로 사용해서는 안된다는 것입니다. 그래서 그의 규칙은 만 사용하는 것입니다 const 인수로서의 참조.

개인적으로, 나는 매개 변수가 출력 매개 변수 일 때 더 명확하게하기 때문에 이것이 좋은 경험 법칙이라고 생각합니다. 그러나 나는 일반적으로 이것에 개인적으로 동의하지만, 출력 매개 변수 (일부 개발자가 엄청나게 좋아하는)로 주장하면 팀의 다른 사람들의 의견에 스스로 흔들릴 수 있습니다.

나는 "cplusplus.com :"의 기사에 의한 추론을 좋아합니다.

  1. 함수가 매개 변수를 수정하지 않으려면 값을 통과하고 값을 복사하기 쉽습니다 (ints, doubles, char, bool 등 ... 간단한 유형. std :: string, std :: vector 및 기타 모든 STL 컨테이너는 단순한 유형이 아닙니다.)

  2. 값이 복사하는 데 비싸고 함수가 지적 된 값을 수정하고 싶지 않을 때 Const 포인터를 통과하고 함수가 처리하는 유효한 예상 값입니다.

  3. 값이 복사하는 데 비싸고 함수가 지적 된 값을 수정하려면 값을 수정하려면 값을 수정하고 NULL이 기능이 처리하는 유효한 예상 값입니다.

  4. Const 참조 값이 복사 비용이 비싸고 함수가 참조 된 값을 수정하려고하지 않으며 포인터가 대신 사용 된 경우 NULL은 유효한 값이 아닙니다.

  5. 값이 복사하는 데 비싸고 함수가 참조 된 값을 수정하려면 비 폰트 참조를 통과합니다. 포인터를 대신 사용하는 경우 NULL은 유효한 값이 아닙니다.

  6. 템플릿 함수를 작성할 때는이 토론의 범위를 벗어난 것으로 간주해야 할 몇 가지 트레이드 오프가 있지만 대부분의 템플릿 기능이 값 또는 (const) 참조별로 매개 변수를 취한다고 말하면 충분합니다. 그러나 반복자 구문은 포인터의 것과 유사하기 때문에 ( "Dereference"에서 별표에서별로), 인수로서 반복자를 기대하는 템플릿 함수는 기본적으로 포인터도 받아 들일 것입니다 (NULL 반복자 개념에 다른 구문이 있기 때문에 NULL을 확인하지 않습니다. ).

http://www.cplusplus.com/articles/z6vu7k9e/

내가 이것에서 취하는 것은 포인터 또는 참조 매개 변수를 선택하는 것 사이의 주요 차이점은 NULL이 허용 가능한 값이라는 것입니다. 그게 다야.

값이 입력인지, 출력, 수정 가능한 등 의지는 결국 기능에 대한 문서 / 주석에 있어야합니다.

이전 게시물에 대한 설명 :


참조는입니다 아니다 널이 아닌 포인터를 얻는 보장. (우리는 종종 그들을 그렇게 취급하지만.)

끔찍하게 나쁜 코드 인이지만, 당신을 목조 뒤에 데려가는 것과 같이 나쁜 코드, 다음은 컴파일 및 실행됩니다. (적어도 내 컴파일러 아래.)

bool test( int & a)
{
  return (&a) == (int *) NULL;
}

int
main()
{
  int * i = (int *)NULL;
  cout << ( test(*i) ) << endl;
};

참고 문헌과 관련된 실제 문제는 다른 프로그래머와 함께 있습니다. 바보, 생성자에 할당 된 사람, 소멸자에서 거래하는 사람, 사본 생성자 또는 연산자 = ()를 제공하지 못합니다.

갑자기 차이의 세계가 있습니다 Foo (바 바) 그리고 foo (바 & 술집). (자동 비트 타이어 복사 작업이 호출됩니다. 소멸자의 거래는 두 번 호출됩니다.)

고맙게도 현대적인 컴파일러는 동일한 포인터 의이 이중 딜로 위치를 선택합니다. 15 년 전, 그들은 그렇지 않았습니다. (GCC/G ++ 하에서 사용 setenv malloc_check_ 0 Dec Unix에서 동일한 기억에서 두 개의 다른 객체에 할당된다. 많은 디버깅 재미 ...


더 실용적으로 :

  • 참고 문헌은 다른 곳에서 저장된 데이터를 변경하고 있다고 숨 깁니다.
  • 참조를 복사 한 객체와 혼동하기 쉽습니다.
  • 포인터는 분명하게 만듭니다!

설마. 내부적으로 참조별로 통과하는 것은 참조 된 객체의 주소를 본질적으로 전달하여 수행됩니다. 따라서 포인터를 통과함으로써 실제로 효율성을 얻지 못했습니다.

그러나 참조로 통과하면 하나의 이점이 있습니다. 전달되는 객체/유형의 인스턴스가 보장됩니다. 포인터를 통과하면 널 포인터를받을 위험이 있습니다. Pass-by-refence를 사용함으로써 함정 된 Null-Check을 한 레벨을 기능의 발신자에게 푸시합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top