C ++에서 참조로 통과하는 것에 대한 포인터를 통과 할 수있는 이점이 있습니까?
-
22-07-2019 - |
문제
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 :"의 기사에 의한 추론을 좋아합니다.
함수가 매개 변수를 수정하지 않으려면 값을 통과하고 값을 복사하기 쉽습니다 (ints, doubles, char, bool 등 ... 간단한 유형. std :: string, std :: vector 및 기타 모든 STL 컨테이너는 단순한 유형이 아닙니다.)
값이 복사하는 데 비싸고 함수가 지적 된 값을 수정하고 싶지 않을 때 Const 포인터를 통과하고 함수가 처리하는 유효한 예상 값입니다.
값이 복사하는 데 비싸고 함수가 지적 된 값을 수정하려면 값을 수정하려면 값을 수정하고 NULL이 기능이 처리하는 유효한 예상 값입니다.
Const 참조 값이 복사 비용이 비싸고 함수가 참조 된 값을 수정하려고하지 않으며 포인터가 대신 사용 된 경우 NULL은 유효한 값이 아닙니다.
값이 복사하는 데 비싸고 함수가 참조 된 값을 수정하려면 비 폰트 참조를 통과합니다. 포인터를 대신 사용하는 경우 NULL은 유효한 값이 아닙니다.
템플릿 함수를 작성할 때는이 토론의 범위를 벗어난 것으로 간주해야 할 몇 가지 트레이드 오프가 있지만 대부분의 템플릿 기능이 값 또는 (const) 참조별로 매개 변수를 취한다고 말하면 충분합니다. 그러나 반복자 구문은 포인터의 것과 유사하기 때문에 ( "Dereference"에서 별표에서별로), 인수로서 반복자를 기대하는 템플릿 함수는 기본적으로 포인터도 받아 들일 것입니다 (NULL 반복자 개념에 다른 구문이 있기 때문에 NULL을 확인하지 않습니다. ).
내가 이것에서 취하는 것은 포인터 또는 참조 매개 변수를 선택하는 것 사이의 주요 차이점은 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을 한 레벨을 기능의 발신자에게 푸시합니다.