c++) const class리턴관련 내용입니다.

zkdnsxjaos의 이미지

class A {

private :
int value;

public :
<생략자 생략>
void setValue( int _value ) { value = _value; }
const A foo( const A& T ) const {
A a;
a = T; <==========<1>
// a.value = 10;
return a; <==========<2>
}
};

void main( ) {
A ah;
A bh;
A ch;
ch = ah.foo(bh); <==========<3>
}

여기서.. 1) const 가 아닌 a 가 const reference T를 할당받는것이 가능한데.. 만약 const A a; 였다면 a = T 할당도 타당하고, a.value = 1 이란 문장도 말이 안되는게 당연한데
const가 아닌 a는 const reference인 T를 할당받았지만 a.value = 10이라는 문장이 가능합니다.. 왜 그럴까요?

2) 그리고 foo의 return 타입이 const A 인데, 실제 리턴되는 a는 const가 아닙니다. 이게 왜 가능한건가요?

3) ch는 const가 아닌데 foo가 리턴한 const class를 할당받을 수 있습니다.. 왜 그런가요?

긴글 읽어주셔서 감사합니다^^

익명 사용자의 이미지

const 객체로부터 non const 객체를 복사 생성하는 것은 가능합니다. 복사도 가능하구요.
const 객체의 non const reference 를 만드는것은 안됩니다.
복사, 복사생성, 레퍼런스의 개념을 정리하실 필요가 있어보입니다.

zkdnsxjaos의 이미지

다시한번 말씀하신 부분 찾아보고 생각을 정리해봤습니다..

klyx의 이미지

1. 혹시 자바로 입문하셨나요? 자바에서는 대입이 레퍼런스 대입이라서 혼동하실수 있는데, C++에서 =는 복사입니다.
a=T는 T를 a에 할당하는게 아니라 T의 값들을 a로 복사하는 겁니다. T가 const 던 아니던 a와는 무관합니다.
물론 연산자 오버로딩으로 실제로 복사가 일어나지 않게 짜는것도 가능은 하지만요.
int a; a=1;이라고 쓰는 것과 하등다를 바가 없습니다. 1도 상수(const int)인 셈이니까요.

2. 마찬가지입니다. 값을 복사한 새로운 객체가 생겨납니다.

3. 마찬가지입니다.

zkdnsxjaos의 이미지

네..제가 자바로 몇년 코딩하다가 c/c++를 전문적으로 다뤄야 해서 기초부터 공부중이었습니다..

만약
a = b라면

= 연산자로 인해 호출객체의 복사생성자가 실행이 되어 parameter로 전달된 상수객체 레퍼런스의 내부값을 a로 복사한다는 말씀이시군요..?
(즉, a의 복사생성자가 const ClassType& b 의 값들을 복사한다는..)

그렇다면 const ClassType으로 리턴된 객체의 값만을 복사하는것이니 실제로 복사생성자를 호출한 객체가 const이니 non-const이니는 상관이 없겠군요..??

klyx의 이미지

적으신건 맞습니다. 참고로 복사 생성자와 대입 연산자는 구분해야 합니다.
A a; a=T; 와 A a=T;는 (기본적으로는)전혀 다른 동작을 합니다. 전자는 먼저 a를 다 할당하고 기본 생성자로 초기화를 한 후에, 대입 연산자(operator=)를 호출하여 T의 값을 복사해옵니다.
후자는 a를 할당하고 (기본생성자가 아니라)복사 생성자를 호출하여 내부 상태를 초기화합니다.
만약 const A a 로 선언하는 경우 복사 생성자를 이용하는 후자는 가능하지만, 전자는 상수로 선언된 후에 대입할 수는 없기 때문에 컴파일에러가 발생합니다.

HDNua의 이미지

#include <iostream>
using std::cout;
using std::cin;
using std::endl;
 
class Test
{
private:
  int num;
  const int cnum;
 
public:
  Test(int num=0, int cnum=0): num(num), cnum(cnum)
  {
    cout<<"생성자 호출"<<endl;
  }
  Test(const Test& test): num(test.getNum()), cnum(test.getCNum())
  {
    cout<<"복사 생성자 호출"<<endl;
  }
 
  int getNum() const   { return this->num; }
  int getCNum() const  { return this->cnum; }
  void setNum(int num) { this->num = num; }
 
  void show() const
  {
    cout<<"Num: "<<num<<endl;
    cout<<"CNum: "<<cnum<<endl;
  }
 
  Test& operator =(const Test& test)
  {
    cout<<"대입 연산자 호출"<<endl;
    num = test.getNum();
    return *this;
  }
};
 
int main(void)
{
  Test t1(5, 5);
  t1.show();
 
  Test t2(t1);  // t2의 복사 생성자 Test(const Test& test)가 호출
  t2.show();
 
  Test t3 = t1; // t3의 복사 생성자 Test(const Test& test)가 호출
  t3.show();
 
  Test t4;      // t4의 생성자 Test(int num=0, int cnum=0) 호출
  t4 = t1;      // t4의 대입 연산자 operator =(const Test& test) 호출
  t4.show();
 
  return 0;
}

위 코드의 출력은 다음과 같습니다.
-----
생성자 호출
Num: 5
CNum: 5
복사 생성자 호출
Num: 5
CNum: 5
복사 생성자 호출
Num: 5
CNum: 5
생성자 호출
대입 연산자 호출
Num: 5
CNum: 0
-----

같은 연산자 =라도, 객체 초기화 시에 사용되면 이 때는 복사 생성자가 호출되고,
초기화 이후에 사용되면 대입 연산자가 호출됩니다.
질문 내용과는 좀 별개의 이야기입니다만 알아두시는 게 좋을 것 같아 적습니다.

저는 이렇게 생각했습니다.

zkdnsxjaos의 이미지

그렇다면 알려주산 내용은

새로운 객체의 선언과 바로 이어서 이미 생성되어 메모리에 로딩되어있는 객체로 초기화를 하는경우엔 새로생성한 객체의 복사생성자가 호출될 것이고..

만일 이미 생성된 객체에 대입연산자를 사용해 할당하게 될 경우는 복사생성자가 호출되지 않는다는 말씀이시군요..!!?

음.. 그렇다면 객체를 위한 대입연산자도 오버로딩을 잘 해두어야겠군요..^^?
(얕은 복사가 발생될 수도 있기때문에..)

HDNua의 이미지

정확합니다.

저는 이렇게 생각했습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.