본문 바로가기
Work/개발 노트

[Study] Effective C++ 문제 제출 후 문제 풀이

by ★용호★ 2011. 7. 22.

2011년 7월 22일 금요일

 한주간 Effective C++을 보고 오기로 하고 일주일이 지났다.  하지만 공부를 제대로 하지 못해서 시험 문제도 부랴부랴 만들었기 때문에 불안불안했다.  역시나 시험 풀이를 해보니 부족한 점이 많았다. 책을 그래도 쭉 보긴 했었는데, 생소한 내용도 많았고 배운 점도 많이 있었다.

- 문제 풀이 내용

1. '값에 의한 전달'보다는 '참조자에 의한 전달' 방식을 택하는 편이 대개 낫다. 라는 말을 되새기며 철수씨는 다음과 같은 함수를 만들었다. 다음 함수는 어떠한 문제를 발생시키는가?

const VECTOR3& AddVector( const VECTOR3& first, const VECTOR3& second )
{
    VECTOR3 ReturnValue( first.x + second.x, first.y + second.y, first.z + second.z );
    return ReturnValue;
}

 ReturnValue AddVector 함수 내에서 선언된 객체 이다. 함수 내에서 선언된 객체는 함수가 종료될 때 소멸이 되는데 보통 반환 시 함수를 호출한 부분에 값 복사가 이루어지지만 이 함수의 반환타입을 보면 ‘&’이 붙어있다. 그러므로 반환 시 값복사가 아닌 함수내의 ReturnValue 객체 자체를 보내게 되는데 이 객체는 함수 종료시 소멸이 됐으므로 비정상적인 값이 반환되게 된다.

2. 철수씨는 다음과 같이 std::string *stringArray = new std::string[100]; 스트링 객체를 생성하고 delete stringArray; 로 메모리를 해제 하였다. 하지만 이 방법은 문제가 있다 어떤 문제인가?

 Std::string[100]으로 메모리를 할당 했으므로 해제할때도 배열의 형태로 해제를 시켜줘야 한다.

3. 철수씨는 아래와 같이 메모리를 동적으로 할당한 다음 메모리를 초기화 하였다. 하지만 초기화한 메모리에 쓰레기 값이 계속 들어가 있어서 혼란에 빠져있다. 왜 이러한 문제가 일어나며, 올바르게 메모리를 초기화 하는 방법은 무엇인가?

bool Array[100][100];
bool ** MyMap;
mapN = 100;
mapM = 100;

myMap = new bPtr[mapN];
for(int i=0;i<mapN;i++) {
    myMap[i] = new bool[mapM];
}
memcpy( Array, MyMap[0], sizeof(bool) * 100* 100);

….??

3. 파일사이의 컴파일 의존성을 줄이는 방법에 대해 말하라.

 .h(헤더파일) 에는 정의 없이 선언만 한다.

 

4. 아래의 메인 함수 내에 문제가 있는지 파악하고 만약 있다면 클래스를 어떻게 변경해야 할지 말하라

Class Base {

private :

           int x;

public :

           virtual void mf1() = 0;

           virtual void mf1(int);

           virtual void mf2();

           void mf3();

           void mf3(int);

};

 

Class Derived : public Base {

public :

           virtual void mf1();

           void mf3();

           void mf4();

};

 

Void main()

{

           Derived d;

           Int x = 5;

          

           d.mf1();

           d.mf1(x);

           d.mf2();

           d.mf3();

           d.mf3(x);

           d.mf4();

}.

Base 클래스에 mf1() mf1(int)가 선언되어 있는데 상속받은 객체에서 이 두가지의 함수를 모두 사용하기 위해서는 using을 사용하거나 super를 이용해야한다.  그렇지 않으면 mf1(int) 함수는 무시된다.

 

5. 상속받은 비가상 함수를 재정의 하면 안되는 이유를 말해보시오.


 

6. 부동산 중개업 지원용 소프트웨어 프로그램을 만든다고 가정한다.

여기서 매물로 내 놓은 가옥은 중복되서는 안되는 유일무이한 객체 이어야 한다.

하지만 클래스를 정의 하면 프로그래머가 정의 하지 않아도 컴파일러는 복사 생성자와 복사 대입 연산자를 자동으로

생성하게 되는데, 따로 처리를 해주지 않으면 복사가 가능하게 되어 버린다.

이러한 상황에서 복사가 되지 않도록 고유한 객체를 만들기 위한 처리를 하는 방법과 friend나 멤버 함수 내에서도

복사가 가능하지 않도록 하는 방법은? (Tip : 기본적으로 복사생성자와 복사대입연산자는 public으로 선언된다.)

1.     Private로 선언한다. 외부에서 접근하려고 할 때 오류를 발생 해준다.

2.     Friend 관계이거나 멤버함수에서 복사를 시도할 경우에는 대입이 가능하므로 프로그래머가 직접 복사 생성자와 복사 대입 연산자를 선언해놓고, 정의는 하지 않는다.

3.     1번의 경우 컴파일 시점에서 오류를 발생시켜주지만 2번의 경우에는 런타임 시점에 오류를 발생시킨다. 오류는 빨리 발견될수록 좋은데, 2번의 경우 런타임 시점의 오류를 컴파일 시점으로 앞당길 수가 있다. 복사 생성자와 복사 대입 연산자의 선언부분을 포함한 추상클래스를 만들어서 상속시키게 되면 2번의 경우 컴파일 시점에 오류를 발생시켜준다.

 

7. 변수 선언시점과 그 이유

사용할 변수들을 미리 다 선언해 놓았을 경우 각 변수마다 메모리를 차지하게 되는데, 함수 수행 도중 해당 변수를 사용하기 전에 return을 만나 함수가 종료되면 변수는 사용되지 않고 쓸데없이 메모리만 낭비한 결과를 초래하게 된다.  그러므로 변수를 적절한 타이밍에 선언을 해야한다.

 

8. value 보다 상수 객체 인자로 전달할시 장점

 객체의 경우 값 복사를 할 때 생성자를 거치고, 복사 대입 연산자를 수행하게 되는데 상수 객체 인자로 전달 시에는 이 과정을 생략할 수 있다.

 

9. const char* get() const

리턴 된 포인터가 가리키는 값을 변경할 수 없다. 함수 시그니쳐 제일 뒤에 const를 붙인 것은 리턴 전용 함수를 의미한다.

10. const int* ptr;

 ptr이 가리키는 값을 변경할 수 없다.

 

11. 연관배열처럼 map사용시 장단점.

 장점 : 사용하기 편리하다.

 단점 : 연관 배열처럼 사용할 때 값 대입 시 default 생성자를 거치므로 시간이 오래걸린다.

 Mapkey가 존재하지 않으면 key를 가진 원소를 삽입하기 때문에 의도치 않은 값이 들어갈 수가 있다.

 


댓글