C ++에서 auto로 변수를 선언하는 데 단점이 있습니까?


143

그 보인다 auto새로운 언어를 많이 따를 것으로 보인다 C ++ 11에 추가 할 수있는 매우 중요한 기능이다. 파이썬과 같은 언어와 마찬가지로 명시 적 변수 선언을 보지 못했습니다 (파이썬 표준을 사용할 수 있는지 확실하지 않습니다).

auto변수를 명시 적으로 선언하는 대신 선언 하는 데 단점이 있습니까?


1
참조 : stackoverflow.com/questions/6434971/… , stackoverflow.com/questions/15254461/… , stackoverflow.com/questions/6900459/… , stackoverflow.com/questions/8430053/is-c11-auto-type-dangerous 그리고 아마도 다른 사람들도 있습니다. 이것이 정확히 중복인지 확실하지 않지만 확실히 후보입니다.
코디 그레이

3
내가 찾은 유일한 단점은 컴파일러가 C ++ 11 기능을 지원하지 않고 지원 할 의도가없는 (콘솔) 플랫폼으로 코드베이스를 이식해야 할 때였습니다!
Sam

7
완전성을 위해 GotW # 94 "거의 항상 자동": herbsutter.com/2013/08/12/…
Richard Critten

1
나는 cppcast를 듣고 있었고 clash b / w auto 및 list initializers에 대한 언급이있었습니다. 나는 그 팟 캐스트를 찾으려고 노력할 것이다.
Abhinav Gauniyal

2
내가 생각하는 첫 번째 단점은 코드의 가독성에 영향을 미친다
ggrr

답변:


111

단점에 대해서만 물어 봤으므로 그 중 일부를 강조하고 있습니다. 잘 사용하면 auto몇 가지 장점도 있습니다. 단점은 남용이 쉽고 코드가 의도하지 않은 방식으로 작동 할 가능성이 높아짐에 따라 발생합니다.

주요 단점은을 사용하여 auto생성되는 객체의 유형을 반드시 알 필요는 없다는 것입니다. 프로그래머가 컴파일러가 한 유형을 추론하기를 기대할 수도 있지만 컴파일러는 다른 유형을 강력하게 추론합니다.

다음과 같은 선언이 주어졌습니다.

auto result = CallSomeFunction(x,y,z);

어떤 유형인지 반드시 알 필요는 없습니다 result. 일 수 있습니다 int. 포인터 일 수 있습니다. 다른 것일 수도 있습니다. 이들 모두는 다른 작업을 지원합니다. 다음과 같은 사소한 변경으로 코드를 극적으로 변경할 수도 있습니다

auto result = CallSomeFunction(a,y,z);

CallSomeFunction()결과 유형 에 어떤 오버로드가 존재하는지에 따라 완전히 다를 수 있으므로 후속 코드는 의도 한 것과 완전히 다르게 작동 할 수 있습니다. 나중에 코드에서 오류 메시지를 갑자기 트리거 할 수 있습니다 (예 :을 역 참조 int하려고 시도하고 현재 무언가 변경하려고 시도 const). 더 불길한 변경은 변경이 컴파일러를 통과하는 곳이지만 후속 코드는 다르고 알 수없는 버그가있는 방식으로 작동합니다.

따라서 일부 변수 유형에 대한 명확한 지식이 없으면 코드가 의도 한대로 작동한다는 주장을 엄격하게 정당화하기가 더 어려워집니다. 즉, 중요도가 높은 (예 : 안전에 중요하거나 미션 크리티컬) 도메인에서 "목적에 적합"하다는 주장을 정당화하려는 노력이 더 많이 필요합니다.

다른 가장 일반적인 단점은 프로그래머가 auto코드의 기능에 대해 생각하고 올바른 코드를 만들기 위해 노력하는 대신 코드를 강제로 컴파일하는 무딘 도구 로 사용하려는 유혹입니다 .


58
이러한 예제가을 사용하는 단점 auto이라면 대부분의 오리 유형 언어는 의도적으로 그러한 단점을 겪고 있습니다.
Leben Asa

11
경우 CallSomeFunction()다른 유형은 인수의 순서에 따라 반환, 그의 설계 결함이다 CallSomeFunction(),하지의 문제 auto. 사용하기 전에 사용중인 함수의 설명서를 읽지 않으면 문제가 아니라 프로그래머의 결함입니다 auto. 하지만 난 당신이 악마의 옹호자를 여기고 있다는 것을 이해합니다.
DevSolar

16
@DevSolar : 왜 T CallSomeFunction(T, int, int)디자인 결함일까요? 분명히 "인수의 순서에 따라 다른 유형을 반환합니다."
MSalters

9
"주된 단점은를 사용하여 auto생성되는 객체의 유형을 반드시 알 필요는 없다는 것입니다." 왜 이것이 auto하위 표현식 임시 문제가 아닌에 문제 가 있는지 자세히 설명 할 수 있습니까 ? 왜 auto result = foo();나쁜가 foo().bar()?
Angew는 더 이상 SO

24
의견에서 "결점"은 용납 할 수없는 이유로 해석되고있는 것 같습니다. 언어 기능의 단점은 개발자가 공학적 상충 관계를 받아들이는지 여부를 고려하고 정당화해야한다는 단점입니다. 이 기능을 사용해야하거나 사용하지 않아야하는 이유에 대해 포괄적 인 주장을하지 않습니다.
피터

76

이것은 auto원칙적으로 정확하게 단점이 아니지만 실제적인 관점에서는 일부에게는 문제가되는 것 같습니다. 기본적으로 일부 사람들은 a) auto유형의 구세주로 취급 하고 사용할 때 두뇌를 차단하거나 b) auto항상 가치 유형으로 추론하는 것을 잊어 버립니다 . 이것은 사람들이 다음과 같은 일을하게합니다 :

auto x = my_obj.method_that_returns_reference();

죄송합니다. 일부 개체를 깊게 복사했습니다. 종종 버그 또는 성능 오류입니다. 그런 다음 다른 방법으로도 스윙 할 수 있습니다.

const auto& stuff = *func_that_returns_unique_ptr();

이제 매달려있는 참조를 얻습니다. 이러한 문제는 전혀 발생 auto하지 않았으므로 이에 대한 합법적 인 주장은 아닙니다. 그러나 auto처음에 열거 한 이유 때문에이 문제를 더 개인적인 것으로 보았습니다 (개인 경험에서).

나는 주어진 시간에 사람들이 조정하고 노동의 분열을 이해한다고 생각 auto합니다. 근본적인 유형을 추론하지만, 당신은 여전히 ​​참조와 정의에 대해 생각하고 싶습니다. 그러나 시간이 조금 걸립니다.


왜 고가의 물건을 딥 카피하여 시작할 수 있습니까?
Laurent LA RIZZA

3
@LaurentLARIZZA : 일부 클래스는 때때로 필요하기 때문에 단순히 복사 생성자를 갖습니다 (예 :의 인스턴스 std::vector). 복사 비용이 많이 드는 것은 클래스의 속성이 아니라 개별 객체의 속성입니다. 따라서 method_that_returns_reference복사 생성자가 있지만 클래스를 복사하는 데 비용이 많이 들고 이동할 수없는 클래스의 개체를 참조 할 수 있습니다.
Marc van Leeuwen

@MarcvanLeeuwen : 객체를 복사하는 데 비용이 많이 들고 이동할 수없는 이유는 std::vector무엇입니까? (그렇습니다, 또는 클래스를 제어하지 못하기 때문에 그것이 중요하지 않습니다.) 복사하는 데 비용이 많이 들고 (복사 가능하기 때문에 리소스를 소유하지 않는 경우) 왜 객체에 COW를 사용하지 않습니까? 데이터 지역은 이미 개체의 크기에 의해 종료되었습니다.
Laurent LA RIZZA

2
@LaurentLARIZZA 벡터에 저장된 객체의 인스턴스는 비싸지 않고, 예를 들어 vector <double>은 복사 비용이 많이 들며 힙 할당 + O (N) 작업입니다. 움직이는 것은 빨간 청어입니다. 표시된 첫 번째 줄은 반환 된 참조가 rvalue 참조가 아닌 한 이동하지 않고 복사합니다. COW는 실제로 여기도 거기도 없습니다. 사실 객체를 복사하는 데 비용이 많이 듭니다.
Nir Friedman

4
@Yakk 슬라이스 할 수 있기 때문에 안전하게 할 수 없습니다. 그것이 할 수있는 유일한 안전은 = delete과부하입니다. 더 일반적으로 당신이 말하는 것은 해결책입니다. nirfriedman.com/2016/01/18/…에 관심이 있으시다면 제가 살펴본 주제 입니다.
Nir Friedman

51

다른 답변은 "변수의 유형이 무엇인지 실제로 모른다"와 같은 단점을 언급하고 있습니다. 나는 이것이 코드의 조잡한 명명 규칙과 관련이 있다고 말합니다. 인터페이스 이름이 명확 하면 정확한 유형 을 신경 쓸 필요가 없습니다 . 물론, auto result = callSomeFunction(a, b);당신에게 많은 말을하지 않습니다. 그러나 정확한 유형을 신경 쓰지 않고 auto valid = isValid(xmlFile, schema);사용할 수 있다고 충분히 알려줍니다 valid. 결국, 그냥 if (callSomeFunction(a, b))을 사용하면 유형도 알 수 없습니다. 다른 하위 표현식 임시 개체와 동일합니다. 그래서 나는 이것이 실제 단점이라고 생각하지 않습니다 auto.

가장 큰 단점은 때로는 정확한 반환 유형이 작업하려는 것이 아니라는 것입니다. 실제로 실제 반환 유형이 구현 / 최적화 세부 사항으로 "논리적"반환 유형과 다른 경우가 있습니다. 식 템플릿이 대표적인 예입니다. 우리가 이것을 가지고 있다고 가정 해 봅시다.

SomeType operator* (const Matrix &lhs, const Vector &rhs);

논리적으로, 우리는을 기대할 SomeType것이며 Vector, 코드에서 그것을 그대로 취급하고 싶습니다. 그러나 최적화를 위해 우리가 사용하는 대수 라이브러리가 표현식 템플릿을 구현할 수 있으며 실제 반환 유형은 다음과 같습니다.

MultExpression<Matrix, Vector> operator* (const Matrix &lhs, const Vector &rhs);

이제 문제는 즉 MultExpression<Matrix, Vector>모든 가능성 상점 A의 의지 const Matrix&const Vector&내부적으로는; Vector전체 표현식이 끝나기 전에 로 변환 될 것으로 예상합니다 . 이 코드가 있다면 모든 것이 잘됩니다.

extern Matrix a, b, c;
extern Vector v;

void compute()
{
  Vector res = a * (b * (c * v));
  // do something with res
}

그러나 auto여기서 사용했다면 문제가 생길 수 있습니다.

void compute()
{
  auto res = a * (b * (c * v));
  // Oops! Now `res` is referring to temporaries (such as (c * v)) which no longer exist
}

3
@NirFriedman 당신이 옳다는 것은 맞습니다. 그러나 실제로 그 auto결점은 거의 없다고 생각합니다 . 그리고 프록시 등의 다른 예는 다양한 "문자열 빌더"및 DSL에서 발견되는 유사한 객체를 포함한다.
Angew는 더 이상 SO

2
나는 식 템플릿과 auto이전에, 특히 Eigen 라이브러리 에 물렸다 . 디버그 빌드에서 문제가 종종 나타나지 않기 때문에 특히 까다 롭습니다.
Dan

1
Armadillo 매트릭스 라이브러리를 사용할 때 최적화를 위해 템플릿 메타 프로그래밍을 많이 사용하는 auto경우에도 사용이 가능 합니다. 다행히 개발자들은 .eval () 함수를 추가하여 다음 과 같은 문제를 피할 수 있습니다.auto
mtall

2
"인터페이스의 이름이 명확하면 정확한 유형을 신경 쓰지 않아도됩니다." 컴파일러는 변수 이름을 연구하여 코드의 정확성을 확인할 수 없습니다. 이것이 유형 시스템의 전체 요점입니다. 맹목적으로 우회하는 것은 바보입니다!
궤도에서 가벼움 경주

1
@ Angew : 일반적으로 즉시 사용하기 때문에 일시적으로 문제가되지 않습니다. auto일반적으로 유형 검사 auto가 필요하지 않습니다. 좋은 비교가 아닙니다.
궤도에서 가벼움 경주

13

단점 중 하나는 때로는로 선언 할 수 없다는 것 const_iterator입니다 auto. 당신은에서 가져온 코드의 예에서 보통 (비 const를) 반복자를 얻을 것이다 이 질문 :

map<string,int> usa;
//...init usa
auto city_it = usa.find("New York");

3
글쎄, 당신은 iterator당신의지도가 아닌이기 때문에 어떤 경우에도 얻을 수 있습니다 const. const_iterator변수 를로 변환하려면 평소와 같이 변수 유형을 명시 적으로 지정하거나지도가의 컨텍스트에 속하도록 메소드를 추출하십시오 find. (나는 후자를 선호한다. SRP.)
Laurent LA RIZZA

auto city_it = static_cast<const auto&>(map).find("New York")? 또는 C ++ 17을 사용 auto city_if = std::as_const(map).find("New York")합니다.
Dev Null

11

코드를 읽기 어렵게하거나 지루하게 만듭니다. 다음과 같은 것을 상상해보십시오.

auto output = doSomethingWithData(variables);

이제 출력 유형을 파악하려면 doSomethingWithData기능의 서명을 추적해야 합니다.


40
항상 그런 것은 아닙니다. 예를 들어 auto it = vec.begin();보다 훨씬 쉽게 읽을 수 std::vector<std::wstring>::iterator it = vec.begin();있습니다.
Jonathan Potter

4
동의했다. 유스 케이스에 따라 다릅니다. 나는 그것에 대해 더 정확했을 수 있습니다.
Skam

1
@SeeDart 예, 자동차를 사용하는 사람들은 잘못하고 있습니다.
lciamp

6
"기능 서명 추적", 마우스로 가리 키거나 키를 누르지 않는 경우 ( "기호 따르기"/ "선언으로 이동"/ 무엇이든) 편집기를 더 구성하거나 구성하지 않고이 작업을 수행 할 수있는 IDE로 전환하십시오 ...하지만 여전히 유효합니다.
hyde

6
체크인을 검토 할 때 IDE가 아니라 작은 구멍이 있음을 알았습니다. 자동차를 사용하면 그러한 이유로 읽기가 더 어렵습니다.
JDługosz

10

개발자 처럼 나는 싫어 auto. 또는 오히려 사람들이 잘못 사용하는 방식이 싫습니다 auto.

나는 타이핑을 줄이는 것이 아니라auto 일반적인 코드를 작성하는 데 도움이 되는 강력한 견해입니다 . C ++는 개발 시간을 최소화 하지 않고 강력한 코드를 작성할 수 있도록하는 언어입니다 . 이것은 C ++의 많은 기능에서 상당히 분명하지만 불행히도 타이핑하는 사람들이 타이핑을 시작해야한다고 생각하는 오타를 줄이려는 것과 같은 새로운 기능 중 일부는 불행합니다 .

auto

이전 auto에는 사람들이 typedefs를 사용 했는데, 이는 typedef 라이브러리 디자이너가 반환 유형이 무엇인지 파악하여 라이브러리가 예상대로 작동하도록 도와 주었기 때문에 훌륭 했습니다. 당신이 사용하는 경우 auto, 당신은 제어 것을 빼앗아 클래스의 디자이너에서 대신이 요청 컴파일러가 타입이 도구 상자에서 가장 강력한 C ++ 도구 중 하나를 제거하고 위험이있는,해야 알아낼 깨고 자신의 코드를.

당신이 사용하는 경우 일반적으로 auto때문일 수 있어야 코드가 작동 어떤 합리적 유형 , 하지 당신이 함께 작동해야 유형을 적어 너무 게으른 때문이다. auto게으름을 돕기 위해 도구로 사용 하는 경우 결국에는 프로그램에서 미묘한 버그 를 도입하기 시작 합니다. 일반적으로을 사용했기 때문에 발생하지 않은 암시 적 변환으로 인해 발생합니다 auto.

불행히도, 이러한 버그는 짧은 예제에서 설명하기가 어렵습니다. 간결성으로 인해 사용자 프로젝트에서 나오는 실제 예제보다 덜 설득력이 있기는하지만 특정 암시 적 변환 이 필요할 것으로 예상되는 템플릿이 많은 코드에서는 쉽게 발생 합니다. 장소.

예를 원한다면 여기 에 하나가 있습니다 . 그러나 약간의주의 사항 : 코드를 뛰어 넘기고 비판하기 전에 : 많은 유명하고 성숙한 라이브러리가 그러한 암묵적 변환을 중심으로 개발되었으며 불가능하지는 않지만 어려울 수있는 문제해결하기 때문에 거기 에 있습니다. 그렇지 않으면 해결하기 위해. 비판하기 전에 더 나은 해결책 을 찾아보십시오 .


3
which was great because typedef allowed the designer of the library to help you figure out what the return type should be, so that their library works as expected. When you use auto, you take away that control from the class's designer and instead ask the compiler to figure out what the type should be실제로 좋은 이유는 아닙니다. 예를 들어 Visual Studio 2015와 같은 최신 IDE를 사용하면 위로 마우스를 가져 가면 변수 유형을 확인할 수 있습니다 auto. 이것은 정확히 * 와 동일합니다 typedef.
솜브레로 치킨

@JameyD : 여기에는 몇 가지 중요한 점이 없습니다. (1) IDE 인수는 형식이 아닌 구체적인 유형 인 경우에만 작동합니다. 종속 유형의 경우 IDE가 올바른 유형을 알려줄 수 없습니다 (예 :) typename std::iterator_traits<It>::value_type. (2) 전체 포인트는 추정 된 유형의 필요가 있다고했다 하지 올바른 유형 코드의 이전 설계자가 의도 한대로 "동일"이; 를 사용 auto하면 올바른 유형을 지정할 수있는 디자이너의 능력이 없어집니다.
user541686

당신은 기본적으로 프록시에 대해 이야기하고 있으며, 대답 중 하나가 이미 언급했습니다. 식 템플릿과 vector <bool> 넌센스는 대부분의 사람들에게 일상적인 코드가 아닙니다. 대부분의 경우 암시 적 변환을 원하지 않으며 자동으로 변환 할 수 있습니다. Herb Sutter는 블로그 게시물 중 하나에서 자동차의 장점에 대해 광범위하게 이야기하고 있으며, 키 입력에 관한 것이 아니라 일반적인 코드 뿐만이 아닙니다. 또한 귀하가 제공 한 첫 번째 링크 인 블로그 게시물은 단순히 끔찍한 조언입니다.
Nir Friedman

@NirFriedman : "... vector<bool>넌센스" ... 사면? 어떻게 bitset구현되고 있다고 생각 하십니까? 아니면 비트 컨테이너가 모두 넌센스라고 생각하십니까?!
user541686

1
@NirFriedman : vector <bool>에 관한 뉴스는 저에게 없습니다. 내가 당신에게 말하려고 노력하고 있으며 당신이 이해하기를 거부하고 있다는 것은 이 질문 의 목적 상 bitset이 vector <bool>과 다르지 않다는 것입니다. 프록시는 유용한 것으로 간주되기 때문에 둘 다 프록시를 사용합니다 그리고 프록시가 유용하다는 사실은 거부하는 대신에 수용해야하는 현실입니다. 프록시가 유용한 지 여부에 대한 토론으로 전환을 중단 할 수 있습니까? 그것은 논쟁의 주제가 아니며, 또한 그들에 대한 당신의 의견은 일종의 사실이 아니라 단지 당신의 의견입니다.
user541686

6

auto그 자체로 는 단점이 없으며 새로운 코드의 모든 곳에서 (손으로 물결 치기) 옹호합니다. 코드가 일관되게 형식을 검사하고 자동 슬라이싱을 피할 수 있습니다. (경우 B에서 유래 A와 함수가 반환 A갑자기 반환 B하고 auto반환 값을 저장하는 데 예상대로 동작)

그러나 C ++ 11 이전의 레거시 코드는 명시 적으로 형식화 된 변수를 사용하여 유도 된 암시 적 변환에 의존 할 수 있습니다. 명시 적으로 유형이 지정된 변수를 auto변경하면 코드 동작이 변경 될 수 있으므로주의를 기울이는 것이 좋습니다.


Downvoting은 공정하지만 그 이유에 대해 의견을 말씀해 주시겠습니까?
Laurent LA RIZZA

나는 당신을 공감하지 않았지만 auto그 자체로 단점이 있습니다 (또는 적어도 많은 사람들이 그렇게 생각합니다). 이 패널의 Sutter, Alexandrescu 및 Meyers와의 토론 에서 두 번째 질문에 제공된 예를 고려하십시오. 가지고 auto x = foo(); if (x) { bar(); } else { baz(); }있고 foo()반환 bool하는 경우 foo()열거 형을 반환하도록 변경하면 (두 가지 대신 세 가지 옵션) 어떻게됩니까? auto코드는 계속 작동하지만, 예기치 않은 결과를 생성합니다.
einpoklum

@einpoklum : 그리고 범위가 지정되지 않은 열거 형의 경우에 bool대신 auto변경 하여 사용 합니까? 나는 틀릴 수 있지만 (여기에서 확인할 수는 없다) 유일한 차이점은 bool의 조건을 평가하는 대신 변수 선언에서 변환이 발생한다는 것입니다 if. enum이 범위에 해당하는 경우, bool명시적인 통지 없이는 로 변환 할 수 없습니다.
Laurent LA RIZZA

4

키워드는 auto단순히 반환 값에서 유형을 추론합니다. 따라서 파이썬 객체와 동일하지 않습니다.

# Python
a
a = 10       # OK
a = "10"     # OK
a = ClassA() # OK

// C++
auto a;      // Unable to deduce variable a
auto a = 10; // OK
a = "10";    // Value of const char* can't be assigned to int
a = ClassA{} // Value of ClassA can't be assigned to int
a = 10.0;    // OK, implicit casting warning

auto컴파일 중에 추론 되기 때문에 런타임에 어떤 단점도 없습니다.


1
예, 기본적으로 type()파이썬에서 수행하는 작업 을 수행합니다. 유형을 추론하고 해당 유형의 새 변수를 만들지 않습니다.
lciamp

2
@lciamp 사실은입니다 decltype. auto변수 할당을위한 것입니다.
큐빅

4

지금까지 아무도 언급하지 않았지만, 당신이 저에게 물었다면 그 자체로 가치가 있습니다.

때문에 (모두가 알고 있어야하는 경우에도 C != C++C로 작성된 코드가 쉽게 C ++ 호환 너무 많은 노력없이 설계 할 수 있으므로 C ++ 코드를 기반을 제공하도록 설계 될 수있다),이 디자인에 대한 요구 사항이 될 수 있습니다.

잘 정의 된 구문 중 일부 C가 유효하지 않은 규칙에 대해 알고 C++있습니다. 그러나 이것은 단순히 실행 파일이 손상되고 알려진 UB-clause가 적용되어 대부분의 시간이 이상한 루핑으로 인해 충돌이나 그 밖의 결과가 발생합니다 (또는 감지되지 않을 수도 있지만 여기서는 중요하지 않습니다).

그러나 이것이 auto처음으로 바뀌는 것은 1입니다 !

auto스토리지 클래스 지정자로 사용하여 코드를 전송 했다고 가정하십시오 . 그것은 심지어 그것이 사용 된 방식에 따라 반드시 "휴식"일 필요는 없다. 실제로는 프로그램의 동작을 자동으로 변경할 수 있습니다.

그것은 명심해야 할 것입니다.


1 최소한 내가 처음 알았을 때.


1
어쨌든 컴파일하려고 할 때 컴파일러 오류가 발생합니다.
솜브레로 치킨

@JameyD : 어떻게 하시겠습니까? 왜 다른 의미를 가진 두 가지 유효한 코드 상황이 오류가 발생해야합니까?
dhein

8
intC 에서 "no type impimps "에 의존하고 있다면 이것으로부터 얻을 수있는 모든 나쁜 것들이 필요하다. 그리고 의존하지 않는다면 , 타입과 함께auto 스토리지 클래스 지정자로 사용 하면 C ++ (이 경우 좋은 것)에서 멋진 컴파일 오류가 발생합니다.
Angew는 더 이상 SO

1
@Angew 잘 그렇습니다. 그렇습니다. 나는 이것을하지 않습니다. 그러나 적어도 명심해야 할 것입니다.
dhein

3

내가 생각할 수있는 한 가지 이유는 당신이 돌아온 반을 강요 할 기회를 잃기 때문입니다. 함수 또는 메소드가 긴 64 비트를 반환하고 32 개의 부호없는 int 만 원하면 제어 할 수있는 기회를 잃습니다.


1
static_cast가 있으며 Meyers의 Effective Modern C ++와 같은 IIRC는 자동 유형 변수의 유형을 지정하는 데 권장합니다.
hyde

2

이 답변 에서 설명했듯이 auto때로는 의도하지 않은 펑키 한 상황이 발생할 수 있습니다. 포인터 유형을 만들 수있는 auto&동안 참조 유형이 있다고 명시 적으로 말해야 auto합니다. 이로 인해 지정자를 모두 생략하면 혼동이 생겨 실제 참조 대신 참조 사본이 생성됩니다.


2
펑키하지 않습니다. 그것이 auto참조와 const유형을 결코 유추하지 않는 것 입니다. 를 들어 auto참조, 당신은 더 나은 사용을 거라고 auto&&. (범용 참조) 유형이 자원을 복사하기에 저렴하지 않거나 소유하지 않는 경우, 유형을 처음부터 복사 할 수 없어야합니다.
Laurent LA RIZZA

1

다른 자극적 인 예 :

for (auto i = 0; i < s.size(); ++i)

부호있는 int comparison between signed and unsigned integer expressions [-Wsign-compare]이므로 경고 ( )를 생성합니다 i. 이것을 피하려면 다음과 같이 작성해야합니다.

for (auto i = 0U; i < s.size(); ++i)

또는 아마도 더 낫습니다 :

for (auto i = 0ULL; i < s.size(); ++i)

1
예, 이것도 자극적입니다. 그러나 언어의 허점이 다른 곳에 있습니다. 이 코드가 실제로 이식성을 갖기 위해서는 size리턴을 가정 할 때 와 같은 리터럴 size_t을 가질 수 있어야합니다 . 그러나이를 수행하기 위해 UDL을 선언 할 수 있습니다. ( )size_t0zsize_t operator""_z(...)
Laurent LA RIZZA

1
순전히 이론적 이의 제기 : 주류 아키텍처 unsigned의 모든 가치를 수용 할만큼 충분히 크지 않을 가능성이 높기 std::size_t때문에, 누군가가 엄청나게 거대한 수의 요소를 가진 컨테이너를 가지고 unsigned있을 경우 , 사용 하면 하위 범위에 무한 루프가 발생할 수 있습니다 지수. 이것이 문제가되지는 않지만 std::size_t의도를 올바르게 나타내는 깨끗한 코드를 얻으려면 사용해야합니다. unsigned long long실제로는 반드시 동일해야하지만 확실 하게 확실하다고 확신하지는 않습니다 .
underscore_d

@underscore_d : 예, 공정 포인트- unsigned long long최소 64 비트가 보장되지만 이론적으로 size_t는 이것보다 클 수 있습니다. 물론 컨테이너에 2 ^ 64 개 이상의 요소가 있다면 걱정할 큰 문제가있을 수 있습니다 ... ;-)
Paul R

1

내가 생각하는 auto독자가 쉽게 & 분명히 유형을 공제 할 수있는, 지역화 된 문맥에서 사용하거나 아니라 해당 유형의 코멘트 나 이름으로 문서화 할 때 좋은 실제의 형태 추론이. 그것이 어떻게 작동하는지 이해하지 못하는 사람들은 그것을 대신 사용하는 것과 같은 잘못된 방법으로 그것을 이용할 수 있습니다 template. 내 의견으로는 좋고 나쁜 사용 사례가 있습니다.

void test (const int & a)
{
    // b is not const
    // b is not a reference

    auto b = a;

    // b type is decided by the compiler based on value of a
    // a is int
}

좋은 용도

반복자

std::vector<boost::tuple<ClassWithLongName1,std::vector<ClassWithLongName2>,int> v();

..

std::vector<boost::tuple<ClassWithLongName1,std::vector<ClassWithLongName2>,int>::iterator it = v.begin();

// VS

auto vi = v.begin();

함수 포인터

int test (ClassWithLongName1 a, ClassWithLongName2 b, int c)
{
    ..
}

..

int (*fp)(ClassWithLongName1, ClassWithLongName2, int) = test;

// VS

auto *f = test;

나쁜 용도

데이터 흐름

auto input = "";

..

auto output = test(input);

기능 서명

auto test (auto a, auto b, auto c)
{
    ..
}

사소한 사례

for(auto i = 0; i < 100; i++)
{
    ..
}

당신이 원하는 경우에 int, 당신은 갈 경우 하나 이상의 문자를 입력해야합니다 auto. 받아 들일 수없는
Rerito

@Rerito 네, int쉽게 볼 수 있고 타이핑 int이 짧습니다. 그렇기 때문에 사소한 경우입니다.
Khaled.K

0

아무도 이것을 언급하지 않은 것에 놀랐지 만, 당신이 무언가의 계승을 계산한다고 가정 해보십시오.

#include <iostream>
using namespace std;

int main() {
    auto n = 40;
    auto factorial = 1;

    for(int i = 1; i <=n; ++i)
    {
        factorial *= i;
    }

    cout << "Factorial of " << n << " = " << factorial <<endl;   
    cout << "Size of factorial: " << sizeof(factorial) << endl; 
    return 0;
}

이 코드는 다음을 출력합니다 :

Factorial of 40 = 0
Size of factorial: 4

그것은 분명히 예상 된 결과가 아니 었습니다. 때문에 그 일이 auto같은 변수 요인의 유형을 추론 int이 할당 되었기 때문에 1.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.