프로그래밍 언어/C++

C++ inline - 9. C++17 이후의 변화

개발_노트 2025. 3. 27. 18:33

9. C++17 이후의 변화

🔹 inline 변수 (inline variable)

C++17 이전의 문제점

C++17 이전에는 헤더 파일에서 변수를 정의하는 것이 까다로웠습니다.

  • 전역 변수를 헤더 파일에 정의하면, 여러 개의 소스 파일에서 포함될 경우 링커 오류(Linker Error) 가 발생할 수 있습니다.
  • 이를 방지하려면 extern 키워드를 사용해야 했습니다.

📌 C++17 이전의 전역 변수 사용 예제
📁 config.h

#ifndef CONFIG_H
#define CONFIG_H

extern int globalValue;  // 선언만 제공 (정의는 다른 소스 파일에 존재)

#endif // CONFIG_H

📁 config.cpp

#include "config.h"

int globalValue = 42;  // 전역 변수의 실제 정의

📁 main.cpp

#include <iostream>
#include "config.h"

int main() {
    std::cout << globalValue << std::endl;  // 42 출력
    return 0;
}

📌 문제점

  • extern을 사용하면 여러 소스 파일에서 동일한 전역 변수를 공유할 수 있지만,
    항상 정의(.cpp 파일)를 따로 제공해야 하는 불편함이 있습니다.
  • 만약 config.h에서 직접 변수를 정의하면 링커 오류 발생 가능성이 큽니다.

C++17 이후: inline 변수를 통한 해결

C++17에서는 inline 변수를 도입하여 헤더 파일에서도 안전하게 전역 변수를 정의할 수 있게 되었습니다.
즉, inline 변수는 중복 정의 문제 없이 여러 번 포함될 수 있습니다.

📌 C++17 이후 inline 변수를 사용한 예제
📁 config.h

#ifndef CONFIG_H
#define CONFIG_H

inline int globalValue = 42;  // C++17 이후에는 헤더 파일에서 정의 가능

#endif // CONFIG_H

📁 main.cpp

#include <iostream>
#include "config.h"

int main() {
    std::cout << globalValue << std::endl;  // 42 출력
    return 0;
}

📌 변경된 점

  • inline int globalValue = 42;를 사용하면 여러 소스 파일에서 config.h를 포함해도 링커 오류가 발생하지 않음.
  • inline 변수를 통해 하나의 전역 변수를 여러 번 정의해도 문제가 발생하지 않음.

inline 변수의 특징

특징 설명
헤더 파일에서 정의 가능 여러 소스 파일에서 포함해도 중복 정의 오류 없음
컴파일러가 한 번만 생성 inline 변수가 포함된 모든 파일에서 같은 객체로 처리됨
extern 불필요 extern 키워드를 사용할 필요 없음

🔹 inline을 활용한 헤더 전용 변수 정의

C++17 이전에는 헤더 파일에서 전역 변수를 정의하는 것이 위험했습니다.
그러나, C++17 이후에는 inline 변수를 사용하여 헤더 전용 변수를 안전하게 정의할 수 있습니다.

📌 예제: 헤더 파일에서 inline을 활용한 전역 변수 정의
📁 constants.h

#ifndef CONSTANTS_H
#define CONSTANTS_H

inline constexpr double PI = 3.141592653589793;
inline constexpr int MAX_USERS = 1000;

#endif // CONSTANTS_H

📁 main.cpp

#include <iostream>
#include "constants.h"

int main() {
    std::cout << "PI: " << PI << std::endl;
    std::cout << "Max Users: " << MAX_USERS << std::endl;
    return 0;
}

📌 설명

  • inline constexpr double PI = 3.141592653589793; → 헤더 파일에서 정의 가능.
  • inline이 없으면 여러 파일에서 포함될 때 링커 오류가 발생할 가능성이 있음.
  • constexpr과 함께 사용하면 컴파일 타임에 상수 값으로 최적화 가능.

inline 변수와 기존 방식(extern) 비교

비교 항목 extern 변수 (C++17 이전) inline 변수 (C++17 이후)
헤더 파일에서 정의 가능 여부 ❌ (정의하면 링커 오류 발생) ✅ 가능
추가적인 .cpp 파일 필요 여부 ✅ 필요 (extern 선언 후 .cpp에서 정의) ❌ 불필요 (헤더 파일에서 바로 정의 가능)
전역 변수 관리 용이성 불편함 (변수마다 extern 선언 필요) 간편함 (헤더 파일에서 직접 관리 가능)

📌 결론

  • C++17 이전 → extern을 사용하여 전역 변수를 선언하고, .cpp 파일에서 정의해야 함.
  • C++17 이후 → inline 변수를 사용하면 헤더 파일에서 직접 전역 변수를 정의할 수 있음.

🔹 inline 변수의 사용 사례

1. 전역 설정 값 저장

#ifndef SETTINGS_H
#define SETTINGS_H

inline int screenWidth = 1920;
inline int screenHeight = 1080;

#endif // SETTINGS_H

📌 설명

  • screenWidth와 screenHeight를 전역 변수로 사용하면서도 여러 소스 파일에서 안전하게 포함 가능.

2. 싱글톤 패턴(Singleton)과 inline 변수 활용

#ifndef LOGGER_H
#define LOGGER_H

#include <iostream>

class Logger {
public:
    void log(const std::string& message) {
        std::cout << "[LOG] " << message << std::endl;
    }
};

// C++17 이전에는 extern Logger logger; 사용
inline Logger globalLogger;  // C++17 이후에는 inline 사용 가능

#endif // LOGGER_H

📁 main.cpp

#include "logger.h"

int main() {
    globalLogger.log("Hello, World!");  // [LOG] Hello, World!
    return 0;
}

📌 설명

  • inline Logger globalLogger;를 사용하면 싱글톤 객체를 전역적으로 정의할 수 있음.
  • extern 없이도 헤더 파일에서 안전하게 전역 객체를 관리할 수 있음.

📌 정리

C++17 이전에는 전역 변수를 헤더 파일에서 정의하면 링커 오류 발생 가능 → extern 필요
C++17 이후 inline 변수를 사용하면 헤더 파일에서 안전하게 전역 변수를 정의할 수 있음
✅ inline 변수는 여러 번 포함해도 단일 객체로 처리되므로 중복 정의 문제 없음
✅ inline constexpr을 사용하면 컴파일 타임에 상수 값으로 최적화 가능
✅ 싱글톤 패턴, 설정 값 관리 등 여러 파일에서 공유해야 하는 변수에 유용

📌 결론
C++17 이후에는 inline 변수를 적극 활용하면 코드의 유지보수성을 높이고, 전역 변수 관리가 더욱 쉬워집니다!