[말랑 퀴즈] 26/10/02 문제
카테고리: MallangQuiz
태그: Quiz
제 말랑말랑 퀴즈 생성기는 이곳에서 확인하실 수 있습니다.
말랑말랑 퀴즈 📝
날짜: 2026-10-02 문제 수: 6문제
Q1. 🔴 어려움
operator new/operator delete를 직접 작성할 때 지켜야 할 관례에 대한 설명으로 가장 올바른 것은?
- A.
operator new는 가용 메모리가 부족하면 즉시bad_alloc예외를 던져야 하며, new 처리자 함수를 호출하는 것은 표준에 어긋난다. - B.
operator new는 0바이트를 요청받아도 적법한 포인터를 반환해야 하고, 파생 클래스 전용 메모리 할당 시 기본 클래스의operator new가 호출되어 크기가 안 맞는(더 큰) 요청이 들어올 수 있으므로, 요청 크기가 자신이 예정한 크기와 다르면 표준operator new를 호출하도록 만들어야 한다. 또한operator new[]는 원시 메모리 덩어리만 할당해야 하는데, 그 안에 들어갈 객체가 몇 개인지·크기가 얼마인지 알 수 없기 때문이다. - C.
operator delete는 항상 매개변수로 받은 포인터가 0이 아님을 보장받으므로, null 포인터 검사를 할 필요가 없다. - D. 클래스 전용
operator delete를 안전하게 쓰려면, 기본 클래스에 가상 소멸자를 두지 않는 편이 좋다 — 그래야 크기 정보가 더 정확히 전달된다.
출처:
game_dev/cpp/chapter8/2025-11-09-cpp_8_51.md
📝 내 선택: B. 이 부분은 잘 모르겠다.
Q2. 🟡 보통
빈칸을 채우시오.
자원 해제를 사람이 직접 delete로 하지 않고, 객체의 ① ___에서 자원을 해제하게 만드는 패턴을 ② ___(이)라고 한다. C++98의 ③ ___는 복사 시 원본을 null로 만들어 유일 소유권을 보장하지만, 이 때문에 내부적으로 복사를 요구하는 ④ ___에는 쓸 수 없다. 참조 카운팅 방식의 ⑤ ___는 이 문제를 해결했지만, ⑥ ___ 참조(예: A가 B를, B가 다시 A를 참조)는 해결하지 못하며, 배열에는 delete []가 필요하므로 이 두 스마트 포인터를 배열에 쓰면 안 된다.
출처:
game_dev/cpp/chapter3/2025-06-09-cpp_3_13.md
📝 내 답: 소멸자, RAII, unique_ptr, 복사 함수, shared_ptr, 순환
Q3. 🟡 보통
다음 명제가 참(O)인지 거짓(X)인지 판단하라.
멤버 함수는 클래스의
public인터페이스라 캡슐화에 영향을 주지 않으므로,clearCache()·clearHistory()·removeCookies()를 순서대로 호출하는 단순 편의 함수는 비멤버 함수보다 멤버 함수로 만드는 것이 캡슐화 측면에서 더 낫다. 다만 프렌드 함수는private멤버에 접근할 수 있어 이런 편의 함수로 쓰기에 특히 안전하다.
출처:
game_dev/cpp/chapter4/2025-06-24-cpp_4_23.md
📝 내 답: X. 멤버 함수는 public 인터페이스면 캡슐화에 영향을 주며, 비멤버 함수로 만드는 것이 캡슐화 측면에서 더 낫다.
프렌드 함수는 private 멤버에 접근할 수 있지만, 안전하진 않다.
Q4. 🟡 보통
TCP 소켓의 송신 버퍼에 대한 설명으로 가장 올바른 것은?
- A. 송신 버퍼는 크기가 완전히 고정되어 있어 프로그래머가 바꿀 수 없으며, 운영체제가 데이터를
push하고 사용자가pop한다. - B. 송신 버퍼는 FIFO 방식으로 동작하며 사용자가
push(), 운영체제가pop()한다. 버퍼가 꽉 차면 빈 공간이 생길 때까지send()가 블로킹되지만, 일반적으로 버퍼가 수천 바이트를 담을 수 있어s.send("hello")처럼 작은 데이터는 즉시 리턴된다. - C.
send()함수는 데이터를 상대방에게 실제로 전달한 뒤에야 리턴되므로, 상대방의 수신 상태와 무관하게 항상 블로킹된다. - D. 송신 버퍼가 가득 차도
send()는 즉시 리턴되며, 대신 전송이 실패했다는 에러 코드를 반환한다.
출처:
server/game_server/3/2026-02-03-game_server_3_3.md
📝 내 선택: B
A: 크기가 고정되어있지 않다. C: 수신 상태에 따라 블로킹되는 것이 아니라, 버퍼 용량에 따라 블로킹되었던것으로 기억한다. D: 버퍼가 가득차면 즉시 리턴되지 않고, 블로킹된다.
Q5. 🔴 어려움
std::make_unique/std::make_shared에 대해 답하시오.
(1) new를 직접 쓰는 것보다 make 함수를 쓰면 좋은 이유 세 가지(코드 중복, 예외 안전성, 효율성)를 각각 한 줄로 설명하시오. (효율성은 make_shared에 한정된 이야기다)
(2) 아래 코드는 왜 자원 누수 위험이 있는가? 컴파일러가 어떤 순서로 코드를 배치할 수 있는지 설명하시오.
processWidget(std::shared_ptr<Widget>(new Widget), computePriority());
(3) make_shared가 메모리 할당을 한 번만 하는 이유는 무엇인가? (new로 직접 만들면 몇 번 할당되는지도 함께 쓰시오.)
(4) make 함수를 쓸 수 없거나 피해야 하는 경우를 두 가지 이상 쓰시오.
출처:
game_dev/moderncpp/4/2026-09-08-moderncpp_4_21.md
📝 내 풀이:
(1) 첫째. new를 사용하면 객체 생성에 타입을 두번 작성해야하지만, make 함수를 쓰면 auto를 통해 한번 작성하면 된다.
둘째. new는 메모리 누수 문제가 터질수 있지만, make_shared는 그렇지 않다.
셋째. 할당 횟수가 줄어든다.
(2) 첫번째 인자 처리 후, 두번째 인자에서 예외가 터지면 누수가 생긴다.
(3) 제어 블록과 객체 생성을 한번에 할당하기 때문이다. new로 만들면 2번 할당된다.
(4) 커스텀 삭제자가 필요한 경우, 중괄호 초기화 리스트가 필요한 경우.
Q6. 🟡 보통 · 📌 오답노트 (2번째 복습)
아래 두 클래스를 보고 답하시오.
class Base {
public:
virtual void mf1() = 0;
virtual void mf1(int);
virtual void mf2();
void mf3();
void mf3(double);
};
class Derived : public Base {
public:
virtual void mf1();
void mf3();
void mf4();
};
(1) Derived d; d.mf1(10);과 d.mf3(3.14);는 각각 컴파일되는가? 안 된다면 정확히 왜 안 되는지, 그리고 d.mf2();는 왜 문제없이 호출되는지 설명하시오.
(2) 이런 “이름 가림” 현상이 매개변수 타입이나 가상/비가상 여부와 무관하게 일어나는 이유(설계 의도)는 무엇인가?
(3) Derived가 Base를 public 상속한다고 할 때, mf1과 mf3의 모든 오버로드 버전을 다시 쓸 수 있게 하려면 어떻게 해야 하는가?
(4) 만약 Derived가 Base를 private 상속하고, mf1의 매개변수 없는 버전만 상속받고 싶다면 (3)의 방법을 쓸 수 없다. 왜 안 되며, 대신 무엇을 써야 하는가?
출처:
game_dev/cpp/chapter6/2025-10-19-cpp_6_33.md오답노트:wn-29fd719b· 2026-09-14 최초 오답 · 이번이 2번째 복습
📝 내 풀이:
(1) 이름 가림으로 인해 컴파일되지 않는다. 이는 접근 지시자, 함수 인자, 가상/비가상에 상관하지 않는다.
mf2는 부모에만 있는 가상함수이기 때문이다.
(2) vtable에서 인자 정보는 포함되지 않은 채 덮어씌워지기 때문으로 아는데, 설계 의도까지는 모르겠다.
(3) using을 통해 사용할 클래스의 함수를 명시한다.
(4) private이기 때문이며, 전달 함수를 사용한다.
댓글남기기