seok9211   3년 전

제가 C하고 헷갈리고 있는 것 같아서 질문드립니다.

vector 를 함수 매개변수로 넘길 때의 & 를 사용하는데 사용했을때 정확히 어떤 의미인지(메모리 구조적으로)

그리고 string 은 &를 써도 안써도 에러가 나지 않고 정상동작하는데 어떤 점이 다른지 궁금합니다.

qahira   3년 전

우리는 C언어 수업에서, 1학년때 매개변수를 넘길때 call by value, call by ref를 통해 넘긴다고 배우는데,

놀랍게도 C에는 call by ref가 엄밀한 의미에서 존재하지 않습니다.


첨부한 코드처럼 매개변수로 포인터를 쓰는 것을 때 call by ref라고 하는 것을 배우셨을 텐데, 

사실은 x라는 포인터 변수(매개변수)에 alpha의 주소값을 "복사"해서 넘기는 것입니다.

제가 이 얘기를 왜하냐면...

vector와 string을 넘긴 것은 각각 call by ref와 value이기 때문입니다.

&없이 그냥 넣은 매개변수의 s1은 main의 s1을 복사해서 만든 별개의 변수가 됩니다. 

즉 main()내의 s1과 solution()의 s1은 서로 완전히 별개이고, 둘 중 뭘 수정해도 서로 영향이 가지 않습니다. 스택에 서로 따로 존재하기 때문입니다.


하지만 v1은 조금? 아니 많이 다릅니다. C++에는 reference value란 것이 있는데, 쉽게 생각하면 딴데서 그 변수에 접근하기 위한 별명이라고 보면됩니다.

main()의 v1은 memory 스택내에서 실존하는 개념입니다. 하지만 solution의 &v1은 스택에 vector로서 존재하지 않습니다. main의 v1의 별명으로서 존재하는 것이지요.

이렇게 하면 큰 이점이 있습니다. 

solution(v1, s1)에서 s1은 main()의 s1을 복사하기 때문에 그만큼 메모리를 추가로 사용하고, 복사하는 데 걸리는 오버헤드가 있습니다.

하지만 레퍼런스를 이용하면 solution.v1과 main.v1은 사실상 동일시 해도 될정도고, 값을 복사하여 클래스를 새로 만들지 않아도 되기 때문에 오버헤드가 더 적습니다.


다만 첨부한 사진처럼 함수 내에서 값을 수정하면 main의 v1에도 영향이 가므로(Side effect) 매우 주의해서 쓰거나, 

특별한 이유가 없다면, const vector<char>& v1 처럼 매개변수의 수정을 불허하여 사용하는 편이 안전합니다.

25291957-a4ee-4d7d-bb18-5eff09fb3ec7

seok9211   3년 전

@qahira

친절한 답변 감사합니다.

제가 이해한 게 맞는지 한번 확인 부탁드려도 될까요?

  1. main 에 vector v1를 선언한다
  2. vector<char> func1(vector<char> v1) 이라는 함수를 만든다.
  3. func(v1)을 하면 메인에 존재하는 v1 과 메모리를 공유하지 않는 독립적은 v1이 생기고 메인의 v1의 내용을 복사해서 새로 만든 v1에 들어간다
  4. 새로 만든 v1을 가지고 연산을 하고 return v1을 하면 새로만든 v1의 내용이 main 의 v1에 덮어 씌워지고 새로만든 v1의 메모리 공간은 사라진다

요게 맞을까요?


qahira   3년 전

네 맞습니다.

좀 더 정확히 표현하자면,

3. s1.operator=()이 호출되어 v1의 내용을 복사합니다.

4. 함수의 return value로 vector<char> 형태의 객체가 나옵니다. 그 객체를 main.v1의 operator=()가 호출되어 기존의 v1을 지우고 복사한다고 생각하시면 됩니다.

* 함수의 리턴은 좀 간략하게 설명했습니다. 

객체들을 사용하실 때 주의해야할 부분이 이점입니다. operator=()가 호출되면 보통 기존의 값을 유지 하지 않고 새객체 만들어서 리턴 합니다. 그래서 복사하는데 오버헤드가 생깁니다.


댓글을 작성하려면 로그인해야 합니다.