C++ Singleton 패턴
스레드 안전한 Singleton 구현입니다. Meyer's Singleton과 std::call_once 방식을 모두 포함하며, 복사/이동 생성자를 삭제하여 단일 인스턴스를 보장합니다.
#include <iostream>
#include <mutex>
#include <memory>
#include <string>
// ─────────────────────────────────────────────
// 방법 1: Meyer's Singleton (C++11 이후 스레드 안전 보장)
// 정적 지역 변수는 최초 호출 시 단 한 번만 초기화됨
// ─────────────────────────────────────────────
class ConfigManager {
public:
// 유일한 인스턴스 접근점
static ConfigManager& getInstance() {
static ConfigManager instance; // C++11: 스레드 안전 초기화
return instance;
}
// 복사 생성자 및 복사 대입 연산자 삭제 → 복제 방지
ConfigManager(const ConfigManager&) = delete;
ConfigManager& operator=(const ConfigManager&) = delete;
// 이동 생성자 및 이동 대입 연산자 삭제 → 이동 방지
ConfigManager(ConfigManager&&) = delete;
ConfigManager& operator=(ConfigManager&&) = delete;
void set(const std::string& key, const std::string& value) {
config_[key] = value;
}
std::string get(const std::string& key) const {
auto it = config_.find(key);
return (it != config_.end()) ? it->second : "";
}
private:
ConfigManager() {
// 기본 설정값 초기화
config_["version"] = "1.0.0";
config_["env"] = "production";
}
~ConfigManager() = default;
std::unordered_map<std::string, std::string> config_;
};
// ─────────────────────────────────────────────
// 방법 2: std::call_once 기반 Singleton
// 더 세밀한 초기화 제어가 필요할 때 사용
// ─────────────────────────────────────────────
class Logger {
public:
static Logger& getInstance() {
std::call_once(initFlag_, []() {
instance_.reset(new Logger()); // 단 한 번만 실행
});
return *instance_;
}
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
Logger(Logger&&) = delete;
Logger& operator=(Logger&&) = delete;
void log(const std::string& message) const {
std::cout << "[LOG] " << message << "\n";
}
private:
Logger() { std::cout << "[Logger] 초기화 완료\n"; }
~Logger() = default;
// 정적 멤버: 플래그와 인스턴스
static std::once_flag initFlag_;
static std::unique_ptr<Logger> instance_;
};
// 정적 멤버 정의
std::once_flag Logger::initFlag_;
std::unique_ptr<Logger> Logger::instance_;
// ─────────────────────────────────────────────
// 사용 예시
// ─────────────────────────────────────────────
int main() {
// Meyer's Singleton 사용
ConfigManager& cfg = ConfigManager::getInstance();
cfg.set("db_host", "localhost");
cfg.set("db_port", "5432");
std::cout << "버전: " << cfg.get("version") << "\n";
std::cout << "DB 호스트: " << cfg.get("db_host") << "\n";
std::cout << "DB 포트: " << cfg.get("db_port") << "\n";
// 동일 인스턴스 확인
ConfigManager& cfg2 = ConfigManager::getInstance();
std::cout << "동일 인스턴스 여부: "
<< (&cfg == &cfg2 ? "true" : "false") << "\n";
// call_once 기반 Logger 사용
Logger::getInstance().log("애플리케이션 시작");
Logger::getInstance().log("설정 로드 완료");
return 0;
}