수색…
비고
키워드 auto
는 자동 추론 된 유형을 나타내는 typename입니다.
C에서 상속 된 C ++ 98에서는 이미 예약어였습니다. 이전 버전의 C ++에서는 변수에 자동 저장 기간이 있음을 명시하는 데 사용할 수있었습니다.
int main()
{
auto int i = 5; // removing auto has no effect
}
그 옛 의미가 제거되었습니다.
기본 자동 샘플
키워드 auto
는 변수 유형의 자동 공제를 제공합니다.
긴 타입의 이름을 다룰 때 특히 편리합니다 :
std::map< std::string, std::shared_ptr< Widget > > table;
// C++98
std::map< std::string, std::shared_ptr< Widget > >::iterator i = table.find( "42" );
// C++11/14/17
auto j = table.find( "42" );
vector<int> v = {0, 1, 2, 3, 4, 5};
for(auto n: v)
std::cout << n << ' ';
람다 와 함께 :
auto f = [](){ std::cout << "lambda\n"; };
f();
유형의 반복을 피하기 위해 :
auto w = std::make_shared< Widget >();
놀랍고 불필요한 사본을 피하려면
auto myMap = std::map<int,float>();
myMap.emplace(1,3.14);
std::pair<int,float> const& firstPair2 = *myMap.begin(); // copy!
auto const& firstPair = *myMap.begin(); // no copy!
복사본의 이유는 반환 된 유형이 실제로 std::pair<const int,float>
!
자동 및 표현식 템플릿
auto
는 또한 표현 템플릿이 작동하는 문제를 일으킬 수 있습니다.
auto mult(int c) {
return c * std::valarray<int>{1};
}
auto v = mult(3);
std::cout << v[0]; // some value that could be, but almost certainly is not, 3.
그 이유는, 즉 operator*
에 valarray
당신에게 지칭 프록시 객체 부여 valarray
지연 평가 수단으로한다. auto
을 사용하면 매달려있는 참조가 생성됩니다. mult
대신 std::valarray<int>
반환 std::valarray<int>
코드는 확실히 3을 인쇄합니다.
자동, const 및 참조
auto
키워드 자체는 int
또는 char
과 비슷한 값 유형을 나타냅니다. const
키워드 및 &
기호로 수정하여 각각 const 유형 또는 참조 유형을 나타낼 수 있습니다. 이 수정자는 결합 될 수 있습니다.
이 예제에서 s
는 값 유형 (유형이 std::string
으로 유추 됨)이므로 for
루프의 각 반복은 벡터에서 s
로 문자열을 복사 합니다.
std::vector<std::string> strings = { "stuff", "things", "misc" };
for(auto s : strings) {
std::cout << s << std::endl;
}
루프의 본문이 s.append(" and stuff")
등)를 호출하여 s
수정하면 원래의 strings
구성원이 아닌이 복사본 만 수정 strings
.
반면에 s
가 auto&
로 선언되면 참조 유형 ( std::string&
유추 됨)이되므로 루프의 각 반복마다 벡터의 문자열에 대한 참조 가 할당됩니다.
for(auto& s : strings) {
std::cout << s << std::endl;
}
이 루프의 본문에서 s
를 수정하면 참조하는 strings
요소에 직접 영향을줍니다.
마지막으로, s
가 const auto&
로 선언되면 const 참조 유형이됩니다. 즉, 루프의 각 반복에 벡터의 문자열에 대한 const 참조 가 할당됩니다.
for(const auto& s : strings) {
std::cout << s << std::endl;
}
이 루프 본문에서 s
는 수정할 수 없습니다 (즉, const가 아닌 메소드를 호출 할 수 없음).
범위 기반 for
루프와 함께 auto
를 사용할 때 불필요한 복사본을 피하기 때문에 루프 본문이 반복되는 구조를 수정하지 않으면 일반적으로 const auto&
를 사용하는 것이 좋습니다.
후행 반환 유형
auto
는 후행 형식의 구문에 사용됩니다.
auto main() -> int {}
이는
int main() {}
주로 std::declval<T>
대신에 매개 변수를 사용하는 decltype
과 결합하면 유용합니다.
template <typename T1, typename T2>
auto Add(const T1& lhs, const T2& rhs) -> decltype(lhs + rhs) { return lhs + rhs; }
일반 람다 (C ++ 14)
C ++ 14에서는 lambda 인수에서 auto
를 사용할 수 있습니다.
auto print = [](const auto& arg) { std::cout << arg << std::endl; };
print(42);
print("hello world");
그 람다는
struct lambda {
template <typename T>
auto operator ()(const T& arg) const {
std::cout << arg << std::endl;
}
};
그리고
lambda print;
print(42);
print("hello world");
자동 및 프록시 개체
때때로 auto
는 프로그래머가 예상했던대로 작동하지 않을 수도 있습니다. 유형 공제가 옳지 않은 경우에도 유형은 표현식을 추론합니다.
예를 들어 프록시 객체가 코드에서 사용될 때 :
std::vector<bool> flags{true, true, false};
auto flag = flags[0];
flags.push_back(true);
이 flag
는 bool
이 아니지만 std::vector<bool>::reference
입니다. 템플릿 vector
의 bool
특수화의 경우 operator []
는 변환 연산자 operator bool
정의 된 프록시 객체를 반환합니다.
flags.push_back(true)
가 컨테이너를 수정하면이 의사 참조는 더 이상 존재하지 않는 요소를 참조하여 flags.push_back(true)
될 수 있습니다.
또한 다음 상황을 가능하게합니다.
void foo(bool b);
std::vector<bool> getFlags();
auto flag = getFlags()[5];
foo(flag);
vector
는 즉시 폐기되므로 flag
는 삭제 된 요소에 대한 의사 참조입니다. foo
호출하면 정의되지 않은 동작이 호출됩니다.
이와 같은 경우 auto
으로 변수를 선언하고 추론 할 유형으로 변환하여 초기화 할 수 있습니다.
auto flag = static_cast<bool>(getFlags()[5]);
그러나 그 시점에서 단순히 bool
을 auto
로 바꾸는 것이 더 합리적입니다.
프록시 객체가 문제를 일으킬 수있는 또 다른 경우는 표현 템플릿 입니다. 이 경우, 템플릿은 때로는 효율성을 위해 현재의 전체 표현식을 넘어 서도록 설계되지 않고 다음에 프록시 객체를 사용하면 정의되지 않은 동작이 발생합니다.