C++의 "auto"

ChangJin·2023년 10월 17일

C++

목록 보기
1/3
post-thumbnail

C++의 'auto' 키워드에 대한 정리

1. 소개

C++ 표준에 정의된 'auto' 키워드는 원래 의미와 수정된 의미가 존재합니다. C++11 이전에는 'auto'는 자동 저장소 클래스에 있는 변수나 지역 변수를 선언하는 역할을 했으나, C++11부터 'auto' 키워드는 초기화식을 통해 형식이 추론되는 변수를 선언하는 역할을 합니다. 이러한 차이로 인해 'auto' 키워드는 C++ 버전에 따라 다르게 동작할 수 있습니다.

2. 'auto'의 예시

#include <iostream>
using namespace std;

int main() {
    int exampleInt = 10;
    int& exampleIntRef = exampleInt;
    auto autoVar = exampleIntRef;

    exampleIntRef = 11;
    cout << exampleInt << " ";

    autoVar = 12;
    cout << exampleInt << endl;
}

위와 같은 경우, 'exampleInt'를 참조하는 변수를 받았으므로 11 12가 출력됩니다.

#include <initializer_list>

int main() {
    // std::initializer_list<int>
    auto listA = { 1, 2 };

    // std::initializer_list<int>
    auto listB = { 3 };

    // int
    auto varC{ 4 };

    // 에러: 'auto'의 형식을 초기화식에서 추론할 수 없음
    auto listD = { 5, 6.7 };

    // 에러: 후행 초기화 문맥에서 'auto'의 형식은 단일 초기화식에서만 추론 가능
    auto listE{ 8, 9 };

    return 0;
}

'listD'와 같이 식을 추론할 수 없거나 'listE'와 같이 여러 변수를 포함하여 초기화하는 방법은 오류를 발생시킵니다.

#include <iostream>
using namespace std;

int increment(int i) {
    return i + 1;
}

int main() {
    auto boolVar = true;
    auto charVar = 'X';
    auto wideCharVar = L'X';
    auto stringVar = "문자열";
    auto intVar = 26;
    auto doubleVar = 3.12;
    auto longVar = 10000000000;

    auto& intRef = intVar;  // 참조
    auto* intPtr = &intVar;  // 포인터

    cout << "값\t\t크기\t\t자료형" << endl;
    cout << boolVar << "\t\t" << sizeof(boolVar) << "\t\t" << typeid(boolVar).name() << endl;
    cout << charVar << "\t\t" << sizeof(charVar) << "\t\t" << typeid(charVar).name() << endl;
    cout << wideCharVar << "\t\t" << sizeof(wideCharVar) << "\t\t" << typeid(wideCharVar).name() << endl;
    cout << stringVar << "\t\t" << sizeof(stringVar) << "\t\t" << typeid(stringVar).name() << endl;
    cout << intVar << "\t\t" << sizeof(intVar) << "\t\t" << typeid(intVar).name() << endl;
    cout << doubleVar << "\t\t" << sizeof(doubleVar) << "\t\t" << typeid(doubleVar).name() << endl;
    cout << longVar << "\t" << sizeof(longVar) << "\t\t" << typeid(longVar).name() << endl;

    auto incrementFunc = increment;  // 함수 포인터
    cout << incrementFunc(3) << endl;

    auto printHello = [] { cout << "hello" << endl; };  // 매개변수 없는 함수, Lambda
    printHello();

    auto incrementBy1 = [](int i) { return i + 1; };  // 매개변수 있는 함수, Lambda
    cout << incrementBy1(3) << endl;

    int count = 0;
    auto addToCount = [&](int i) { count += i; };  // 함수 자체(함수 내부에서 외부 변수 참조 시 & 대입), Lambda

    auto returnByReference = [](int* i) -> int& { return *i; };  // 함수 자체(참조자를 리턴하려는 경우), Lambda
}

그러나 몇 가지 경우에서는 'auto'를 사용할 수 없습니다.

  • 함수 매개변수: 'auto' 키워드는 함수의 매개변수로 사용할 수 없습니다.
void add(auto a, auto b) {}  // 오류
  • 구조체나 클래스의 멤버 변수: 'auto' 키워드는 해당 객체의 자료형 크기를 정할 수 없기 때문에 구조체나 클래스의 멤버 변수로 사용할 수 없습니다. 그러나 반환 형식으로는 사용 가능합니다.
struct {
    auto memberB;
}

class Person {
    auto name;
}

3. 'auto'와 후행 반환 형식

'auto'를 사용하는 함수에서 후행 반환 형식을 지정할 수 있습니다. 후행 반환 형식을 지정하면 함수의 반환 형식을 명시적으로 지정할 수 있습니다.

auto returnDouble() {     // 에러: 후행 반환 형식을 지정하지 않음
    return 3.2;
}

auto returnDouble() -> double {  // 정상: 함수 뒤에 후행 반환 형식을 지정
    return 3.2;
}

후행 반환 형식을 지정하면 함수의 반환 형식을 명시적으로 지정할 수 있으며, 이것은 함수 템플릿과 함께 사용하면 유용합니다.

template<typename Param1, typename Param2>
auto add(Param1 p1, Param2 p2) -> decltype(p1 + p2) {
    return p1 + p2;
}

위의 'add' 함수에서는 'int'형과 'double'형이 매개변수로 들어오면 'decltype'에서 'p1'과 'p2'를 더해서 'double'이 되고, 'auto'는 자동으로 'double

' 형태로 반환됩니다. 이렇게 'decltype'을 이용하여 반환 형식을 예측 가능하게 만들 수 있습니다.

이러한 방법은 함수 템플릿을 사용하는 상황에서 인수의 자료형 순서를 알 수 없는 경우에 유용합니다. 'auto'와 'decltype'을 함께 사용하여 더 큰 자료형을 반환하고자 할 때, 'decltype'을 이용하여 'double' 형식을 반환할 수 있도록 만들 수 있습니다.

만약 'auto'를 사용하지 않는다면 사용자는 모든 경우의 자료형을 갖는 함수를 작성해야 합니다.

int add(int a, int b);
double add(int a, double b);
double add(double a, int b);
double add(double a, double b);

더 다양한 자료형을 다루어야 하는 경우, 함수 템플릿과 'auto'를 함께 사용하면 하나의 함수 작성으로 끝낼 수 있습니다.

4. 결론

'auto'를 사용하면 코드 작성이 더 간편해지고 개발자의 생산성을 높일 수 있습니다. 그러나 무분별한 사용은 자료형 파악을 어렵게 하고 코드의 가독성을 떨어뜨릴 수 있습니다. 따라서 코드 컨벤션을 준수하면서 적절한 상황에서 'auto'를 사용하면 아름다운 코드를 작성할 수 있을 것입니다.

5. 참고 자료

profile
게임 프로그래머

0개의 댓글