• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    미해결

4:30 부근 질문입니다.

23.03.22 16:49 작성 조회수 241

2

ref를 함수 인자로 넘기면 변수의 복사가 일어나는게 아니라 변수를 직접 넘기는 것은 이해했습니다.

아래 질문들을 보고 const ref에는 literal도 대입될 수 있다는 것도 이해했구요.

그런데, const ref를 함수 인자로 쓰면 literal을 함수 인자로 그대로 쓰는 게 장점이라고 강의에 말씀하셨는데, 그건 그냥 일반 변수를 인자로 받는 함수도 마찬가지 아닌가요? 그게 왜 장점이 되는지 모르겠습니다.

아래 코드에서 보시면, doSomething과 doSomething2 역시 doSomething4와 동일하게 literal을 인자로 받을 수 있습니다.

literal을 함수 인자로 쓰는 경우는 메모리 주소가 필요한 상황이 아니니(애초에 literal은 R-value니까) 위에서 언급하신 "변수 복사가 아니라 같은 주소값을 갖는 그 변수 자체가 넘어간다"는 이점도 없어보입니다. literal을 인자로 받는 함수에서 인자를 const ref로 받는 것이 정말 다른 경우에 비해 효용성이 큰가요?

 

#include <iostream>

using namespace std;

void doSomething(const int x) {

cout << "In doSomething : " << x << endl;

cout << "In Dosomething : " << &x << endl;

}

void doSomething2(int x) {

cout << "In doSomething2 : " << x << endl;

cout << "In Dosomething2 : " << &x << endl;

}

void doSomething3(int& x) {

cout << "In doSomething3 : " << x << endl;

cout << "In Dosomething3 : " << &x << endl;

}

void doSomething4(const int& x) {

cout << "In doSomething4 : " << x << endl;

cout << "In Dosomething4 : " << &x << endl;

}

int main() {

int x = 5;

int& ref_x = x;

/*ref를 쓰기 위해선 메모리 주소가 있어야 하기 때문에 literal은 대입 불가. 즉,

int& ref1 = 5;

int& ref2 = 3 + 4;

는 불가능.그러나, const ref는 가능.즉, 아래 코드는 가능. 주소값도 있음*/

const int& ref3 = 3;

cout << ref3 << endl;

cout << &ref3 << endl;

/*심지어 주소도 있음. 그럼 이게 const int ref3 = 3;이랑 뭐가 다르냐?

함수 파라미터로 넣을 때 아주 유용함*/

doSomething(ref3);

cout << ref3 << endl;

cout << &ref3 << endl;

doSomething2(ref3);

cout << ref3 << endl;

cout << &ref3 << endl;

doSomething4(ref3);

cout << ref3 << endl;

cout << &ref3 << endl;

doSomething(90);

doSomething2(90);

doSomething4(90);//const ref를 함수 입력인자로 받으면 literal 직접 입력 가능

return 0;

}

답변 2

·

답변을 작성해보세요.

2

Soobak님의 프로필

Soobak

2023.03.22

안녕하세요, 답변 도우미 Soobak 입니다. 😀

질문 주실 때 마다, 항상 질문 하신 강의 중 궁금하신 부분의 시간을 알려주셔서 참 감사드립니다!! 😁👍

강의 1.7 지역 범위 10:01 부분의 자료 화면과, 강의 4.1 지역변수, 범위, 지속시간 전반에 걸친 내용을 복습해보시면 "함수가 정의된 영역 안 또한 하나의 지역 범위" 입니다. 또한, 강의 6.14 참조 변수 reference variable7:35 부분에서 학습하셨듯이, 함수를 void doSomthing(int x) 처럼 선언하고 호출할 시에는 변수의 복사가 일어나게 되고, 함수의 매개변수의 메모리 주소와 함수를 호출한 곳의 인자의 메모리 주소가 다릅니다.

이해를 돕기 위하여 아래의 코드와 출력 결과를 첨부합니다.

void doSomething(int x)
{
  cout << "In Dosomething, address of x : \t[" << &x << "]" << endl;
}

int main()
{
  int x = 123;
  cout << "In main, address of x : \t[" << &x << "]" << endl;
  doSomething(x);
  cout << "In main, address of x : \t[" << &x << "]" << endl;
  return 0;
}
  • 출력결과

    image

하지만, 강의 6.14 참조 변수 reference variable10:25 부분에서 학습하셨듯이 참조를 통하여 호출을 하게 된다면 함수의 매개변수의 복사가 일어나지 않게 되므로, 함수가 정의된 영역 안과 밖에서 같은 메모리 주소를 갖게 됩니다.

이해를 돕기 위하여 아래의 코드와 출력 결과를 첨부합니다.

void doSomething(int &x)
{
  cout << "In Dosomething, address of x : \t[" << &x << "]" << endl;
}

int main()
{
  int x = 123;
  cout << "In main, address of x : \t[" << &x << "]" << endl;
  doSomething(x);
  cout << "In main, address of x : \t[" << &x << "]" << endl;
  return 0;
}
  • 출력 결과
    image

따라서, 일반적인 경우에서 함수의 매개변수를 reference 로 선언하는 것이 메모리를 보다 효율적으로 사용할 수 있게 됩니다.

하지만, const 한정자 없이 일반적인 참조형으로 함수의 매개변수를 선언하면 R-value를 인자로하여 함수를 호출할 수 없습니다.
강의 1.3 변수와의 첫 만남12:08 부분에서 학습하셨듯이, R-value 는 임시적으로 메모리의 읽기 전용 공간에 저장되게 되며, 강의 6.14 참조 변수 reference variable 과 질문해주신 강의 6.15 참조와 const 에서 학습하셨듯이, 참조형 변수는 기존 변수에 대한 별명과도 같은 역할을 하며, 기존 변수를 가리키도록 설계되었으므로 literal 값이나 익명 객체 등을 참조할 수 없기 때문입니다.
(익명 객체에 대해서는 추후 강의 8.13 익명 객체 에서 보다 자세히 학습하시게 되며, 참조에 관한 내용 역시 해당 강의에서 복습하시게 됩니다.)

여기서, 질문해주신 강의에서 학습하셨듯이, 일반적인 reference 는 R-value 의 참조가 불가능하지만, const reference 는 R-value 에 대한 참조가 가능합니다.

따라서, 함수의 매개변수를 const reference 로 선언하게 되면, 함수의 인자로 변수를 넣어도 함수의 호출이 가능할 뿐만 아니라, R-value 를 함수의 인자로 넣어도 함수의 호출이 가능하게 되어 보다 다양한 경우에서 편리하게 함수를 호출할 수 있게 되는 것입니다.

해당 부분은 질문해주신 강의 4:05 부분의 자료 코드와 교수님의 설명을 참고하시면 이해하시는 데에 도움이 되실 것 같습니다.

void doSomething(const int& x)
{
  cout << x << endl;
}

int main()
{
  int a = 1;

  doSomething(a);
  doSomething(1); // <--- 가능!
  doSomething(a + 3); // <--- 가능!!
  doSomething(3 * 4); // <--- 가능!!!

  return 0;
}

 

또 궁금하신 점 있으시면 언제든지 편하게 질문글 남겨주세요. 감사합니다. 👍😀😁

 

1

Something1()과 Something2()는 복사가 일어납니다.

Something3()에서는 복사는 일어나지 않지만 실수로 함수 내부에서 x를 수정할 수도 있습니다. (x를 함수 내부에서 수정하려고 의도한 경우에는 상관 없습니다.)

Something4()에서는 복사도 일어나지 않고 실수로 함수 내부에서 x를 수정할 수도 없습니다.

매개변수의 자료형이 int 같이 작은 경우에는 요즘 컴퓨터에서는 속도 차이가 거의 없을 수도 있습니다. int 대신 아주 큰 자료형(구조체나 클래스)일 경우에는 복사를 피하는 것이 도움이 많이 됩니다.