학습
C++ 최신 C++ 표준의 변화
C++ 최신 C++ 표준의 변화 — 고급
최신 C++ 표준의 변화
1. 도입 (왜 배워야 하는가)
최근 C++ 표준은 프로그래밍 언어로서의 C++의 가능성을 한층 더 확장하고 있습니다. C++11, C++14, C++17, C++20 그리고 최근의 C++23 버전은 성능과 생산성을 높이기 위한 다양한 기능을 추가했습니다. 이러한 변화는 특히 대규모 프로젝트나 시스템 프로그래밍, 게임 개발 등에서 중요한 역할을 합니다.
이러한 최신 표준을 모르고 구식의 문법이나 기능에 의존하게 되면, 코드의 유지보수성이 떨어지고, 성능 최적화 기회를 놓치는 등의 문제가 발생할 수 있습니다. 예를 들어, C++11에서 추가된 std::shared_ptr와 같은 스마트 포인터를 사용하지 않는다면 메모리 관리에서 많은 오류가 발생할 수 있습니다.
2. 핵심 개념 설명
2.1. 스마트 포인터
스마트 포인터는 메모리 관리를 자동화하여 메모리 누수를 방지하는 객체입니다. 일반 포인터가 마치 친구의 집에 놀러간 것이라면, 스마트 포인터는 집주인과 함께 있는 친구와 같습니다. 집주인이 집을 관리하므로 친구는 걱정할 필요가 없습니다.
| 용어 | 설명 |
|---|---|
std::unique_ptr | 소유권이 하나만 존재하는 포인터 |
std::shared_ptr | 여러 포인터가 같은 메모리를 공유하는 포인터 |
std::weak_ptr | std::shared_ptr와 함께 쓰이며, 순환 참조를 방지하는 포인터 |
2.2. 범위 기반 for 루프
범위 기반 for 루프는 컨테이너의 요소를 순회할 때 코드의 가독성을 높여줍니다. 일반 for 루프가 길고 복잡하다면, 범위 기반 for 루프는 마치 친구와 함께 간단히 음식을 나누는 것과 같습니다.
3. 기본 코드 예제
아래는 스마트 포인터의 기본적인 사용법을 보여줍니다.
#include <iostream>
#include <memory>
int main() {
// std::unique_ptr 생성
std::unique_ptr<int> ptr(new int(5)); // 5라는 값을 가지는 정수 포인터 생성
std::cout << *ptr << std::endl; // 포인터가 가리키는 값 출력
// ptr이 범위를 벗어나면 자동으로 삭제됨
return 0;
}
실행 결과
5
코드 한 줄씩 동작 설명
#include <iostream>: 입출력 스트림을 사용하기 위해 필요한 헤더 파일 포함.#include <memory>: 스마트 포인터를 사용하기 위해 필요한 헤더 파일 포함.std::unique_ptr<int> ptr(new int(5));: 정수 5를 가리키는 스마트 포인터 생성.std::cout << *ptr << std::endl;: 포인터가 가리키는 값을 출력.return 0;: 프로그램 종료시 포인터가 자동으로 메모리 해제.- 잘못된 코드:
- 올바른 코드:
- 잘못된 코드:
- 올바른 코드:
- 최신 C++ 표준의 변화는 코드의 가독성과 성능을 크게 향상시킵니다.
- 스마트 포인터와 범위 기반 for 루프는 메모리 관리와 코드 단순화를 돕습니다.
- 실무에서의 리소스 관리와 장바구니 구현 등에서 유용하게 사용됩니다.
- C++의 병행성 (Concurrency) 및 멀티스레딩
- 템플릿 프로그래밍과 메타프로그래밍
- C++의 새로운 기능: C++23의 주요 변화
4. 실전 활용 예제
4.1. 쇼핑몰에서 장바구니 구현
#include <iostream>
#include <memory>
#include <vector>
class Item {
public:
Item(std::string name) : name(name) {}
std::string name;
};
class Cart {
public:
void addItem(std::shared_ptr<Item> item) {
items.push_back(item);
}
void showItems() {
for (const auto& item : items) {
std::cout << item->name << std::endl;
}
}
private:
std::vector<std::shared_ptr<Item>> items;
};
int main() {
Cart cart;
cart.addItem(std::make_shared<Item>("사과"));
cart.addItem(std::make_shared<Item>("바나나"));
cart.showItems(); // 장바구니에 담긴 아이템 출력
return 0;
}
상황 설명
쇼핑몰에서 장바구니를 구현할 때, 여러 사용자가 같은 아이템을 장바구니에 담을 수 있습니다. 이때 std::shared_ptr를 사용하여 메모리 관리를 자동화할 수 있습니다.
4.2. 리소스 관리
#include <iostream>
#include <memory>
class Resource {
public:
Resource() { std::cout << "Resource acquired" << std::endl; }
~Resource() { std::cout << "Resource destroyed" << std::endl; }
};
void useResource() {
std::unique_ptr<Resource> res(new Resource());
// Resource 사용
}
int main() {
useResource(); // 리소스 사용
return 0;
}
5. 흔한 실수와 주의사항
5.1. 스마트 포인터 사용 시 주의사항
std::shared_ptr<int> ptr1(new int(10));
std::shared_ptr<int> ptr2 = ptr1; // ptr1과 ptr2는 같은 메모리를 참조
문제: 순환 참조를 발생시킬 수 있습니다.
std::shared_ptr<int> ptr1(new int(10));
std::weak_ptr<int> ptr2 = ptr1; // ptr2는 ptr1의 약한 참조
5.2. 범위 기반 for 루프 사용 시 주의사항
std::vector<int> numbers = {1, 2, 3};
for (int i = 0; i < numbers.size(); i++) {
std::cout << numbers[i] << std::endl; // 인덱스 사용
}
for (const auto& number : numbers) {
std::cout << number << std::endl; // 범위 기반 for 루프 사용
}