C++의 reference와 pointer

mandami의 이미지


C++을 꽤 오랫동안 C처럼 만지고 난 후, 이제서야 C++을 좀 C++스럽게 사용하고 있습니다.

지꿎게도 자바 프로젝트 경험이 C++을 쓰는데 많은 도움이 되네요.

그덕에 C 시절의 버릇 여럿을 버렸지만, 그래도 그래도 버리지 못한 것이 있으니 reference와 pointer입니다.

제가 reference 대신 pointer로 인자를 넘기는 이유는 다음과 같습니다.

첫째, 함수 호출자 입장에서의 혼란

그냥 draw( surface ); 해버리면, surface가 call by reference로 넘어갔는지, call by value로 넘어갔는지 모호합니다.
만약 pointer로 넘기면, &surface로 '아, 포인터로 넘어갔구나'라는걸 압니다. 그리고 '저 함수 안에서 이 변수가 수정될 가능성도 있겠구나'라는걸 압니다.

하지만 reference로 넘어가면 이걸 구분하기 귀찮아집니다.

둘째, null처리

reference의 경우 null처리를 할 필요가 없다, 는 것이 장점으로 꼽히지만 예외처리를 할때는 그래도 null을 이용하는게 편하더군요.

try, catch문이 있지만, 복잡한 예외처리가 아닌, 순수 'null을 반환할 필요'가 있는 경우에 reference를 사용하면 문제가 복잡합니다.

셋째, 통일성

솔직히 지금 사용하는 라이브러리들이 C 시절부터 쓰이던 것들이 상당수 입니다. 그것들은 당연히 pointer를 사용하고 있구요.

그러다 보니, reference를 쓰게 되면 pointer와 섞이게 되고, 그렇게 되면 상당히 혼란스러워집니다.

라이브러리를 업그레이드해서 reference로 바꾸기에도 위에서 말했던 null처리가 어려워지구요.

그래서 class, namespace, stl, template등등은 쓰겠지만, reference(더불어 cout)은 아직 손이 가지 않네요.

다른 분들의 경험담 및 느낌을 듣고 싶습니다.

neogeo의 이미지

reference type 을 꼭 고집할 필요는 없다고 생각합니다. C++ 은 굉장히 유연하므로 아무거나 섞어써도 되게 만들어둔것이니까요.

종종 reference type 이 편한경우가 있습니다. ( 저같은 경우 문자열이 특히 그랬습니다. char * 가 아닌 String 계열 .. )
그리고 변수의 변경 수정 여부는 const 로 구분하는것이 좀 더 낫습니다. 포인터 역시도 내용을 바꿀 수는 있지만, 바뀔지 아닐지 알 수 없는건 보내는 입장에선 마찬가지니까요. 보낼때 const cast를 붙여서 보낸다던가 받는 측도 const reference 로 받아서 쓴다던가 하면, 상당히 편리하며 컴파일러 입장에선 최적화에 굉장히 많은 힌트를 얻을 수 있습니다. 또한 operator overloading 을 자주 사용할 경우 수식의 확장과 연결에 reference type 이 아니면 상당히 골치가 아픈 경우가 많습니다. reference type 이 일반 변수보다 당연히 overhead 도 적을 확률이 높고요. ( pointer 와는 같은 수준이겠죠 )

내용 바뀌는 여부만 가지고 pointer 와 call by value 를 위한 copy 사용을 구분하면 상당히 프로그램 퍼포먼스에 나쁜 영향을 줄 수 있습니다. class 나 4 byte 를 넘는 data type 은 때로는 pointer 나 reference type 으로 주고 받는 것이 굉장히 overhead 를 줄일 수 있기 때문입니다. 따라서 상수적인 data 를 보낸다고 해도, 반드시 덩치가 큰 것이면 pointer 나 reference 에 const 를 붙여서 주고받기를 권장합니다.( 프로그래머가 귀찮더라도 반드시 편의적으로 바뀌는건 포인터 , 바뀔지 아닐지 모르지만 여하튼 변수 그대로 , 이렇게 구분하는건 굉장히 좋지 않습니다. 반드시 사이즈가 큰거나 작더라도 바뀔 수 있는것 -> 포인터 or 레퍼런스, 사이즈가 작으면서 바뀌지 않는 상수값 -> value , 그리고 귀찮더라도 되도록 확실히 상수값으로 사용하는 인자는 const 를 붙여서 받을것. 보낼때도 바뀌지 않기를 원하는것을 확실히 표시하고 싶으면 const cast 를 활용하십시오. 그러면 가독성이 크게 늘면서 성능도 좋게 하실 수 있습니다. )

Neogeo - Future is Now.

Neogeo - Future is Now.

klyx의 이미지

말씀중에 궁금한 것이 있는데, const cast의, 형변환 자체의 오버해드는 무시할수 있는 수준인 것인가요...?

lifthrasiir의 이미지

const_cast는 타입 자체를 바꾸는 게 아닌 타입의 속성(변경하려고 하면 컴파일 에러를 내느냐)만을 바꾸기 때문에 오버헤드가 없습니다. C++에서 캐스팅이 오버헤드를 내는 일반적인 경우는 dynamic_cast를 쓰는 경우겠죠.

hongminhee의 이미지

저는 반대로 포인터보다 참조가 더 편해서 자주 씁니다. 꼭 null 처리를 해야할 필요가 있을 때만 포인터를 사용합니다. 메서드가 인자로 들어온 객체를 수정하는 일은 애초에 피합니다.

asitgoes의 이미지

reference를 쓰는게 깔끔해지기는 하는데, STL에 객체들을 저장하거나 해야 할때는 어쩔 수 없이 pointer를 써야 하는 경우게 있어서 pointer를 쓰게 되더군요. 두개를 섞어쓰면 오히려 더 지저분해지곤해서..

----------------------------
어떻게든 되겠지..

----------------------------
어떻게든 되겠지..