Programming

C ++ 11 자동 키워드가 너무 많습니까?

procodes 2020. 5. 5. 20:58
반응형

C ++ 11 자동 키워드가 너무 많습니까?


auto복잡한 템플릿 형식에 대해 C ++ 11 표준에서 사용할 수 있는 새로운 키워드를 사용하고 있습니다. 그러나 나는 또한 그것을 다음과 같은 것들에 사용하고 있습니다 :

auto foo = std::make_shared<Foo>();

그리고 더 회의적으로 :

auto foo = bla(); // where bla() return a shared_ptr<Foo>

나는이 주제에 대해 많은 논의를 보지 못했다. auto유형은 종종 문서 및 위생 검사의 한 형태이기 때문에 과도하게 사용될 수있는 것 같습니다 . 사용 라인을 어디 auto에서 그리고이 새로운 기능에 권장되는 사용 사례는 무엇입니까?

명확히하기 위해 : 나는 철학적 의견을 요구하지 않습니다. 표준위원회에서이 키워드의 의도 된 사용을 요청하고 있습니다. 아마도 그 의도 된 사용이 실제로 어떻게 실현되는지에 대한 의견이있을 것입니다.

참고 :이 질문은 SE.Programmers로 옮겨졌다가 다시 Stack Overflow로 돌아 왔습니다. 이것에 대한 논의는이 메타 질문 에서 찾을 수 있습니다 .


auto첫눈에 유형을 작성하는 방법을 말하기가 어려울 때마다 키워드를 사용해야한다고 생각 하지만 표현식의 오른쪽 유형은 분명합니다. 예를 들어,

my_multi_type::nth_index<2>::type::key_type::composite_key_type::
    key_extractor_tuple::tail_type::head_type::result_type

boost::multi_index비록 당신이 알고 있지만 복합 키 유형을 얻을 수 있습니다 int. int나중에 변경 될 수 있기 때문에 글을 쓸 수 없습니다 . 나는 쓴다 auto,이 경우.

따라서 auto키워드가 특정 경우에 가독성을 향상시키는 경우 사용하십시오. auto유형이 무엇을 auto나타내는 지 독자에게 분명 할 때 쓸 수 있습니다 .

여기 몇 가지 예가 있어요.

auto foo = std::make_shared<Foo>();   // obvious
auto foo = bla();                     // unclear. don't know which type `foo` has

const size_t max_size = 100;
for ( auto x = max_size; x > 0; --x ) // unclear. could lead to the errors
                                      // since max_size is unsigned

std::vector<some_class> v;
for ( auto it = v.begin(); it != v.end(); ++it )
                                      // ok, since I know that `it` has an iterator type
                                      // (don't really care which one in this context)

부작용이 걱정되는 일이 없도록 auto가능한 모든 곳에서 사용하십시오 const auto. 명백한 경우를 제외하고 유형에 대해 걱정할 필요는 없지만 정적으로 확인되므로 반복을 피할 수 있습니다. 어디 auto가능하지, 당신은 사용할 수 있습니다 decltype로 의미 유형을 표현하는 계약 식을 기반으로. 코드는 다르게 보일 것이지만 긍정적 인 변화가 될 것입니다.


쉬운. 유형이 무엇이든 상관하지 않을 때 사용하십시오 . 예를 들어

for (const auto & i : some_container) {
   ...

내가 여기에서 신경 쓰는 i것은 컨테이너에있는 것입니다.

typedef와 비슷합니다.

typedef float Height;
typedef double Weight;
//....
Height h;
Weight w;

여기에, 난 상관 여부하지 않는 hw그들이 단지 것을, 수레 또는 복식있는 높이와 무게를 표현하기에 적합하다 어떤 유형 .

아니면 고려

for (auto i = some_container .begin (); ...

여기서 내가 걱정하는 것은 그것이 적절한 반복자이며 지원하는 operator++()것입니다.이 점에서 오리 타이핑과 같습니다.

또한 람다의 유형은 철자가 될 수 없으므로 auto f = []...좋은 스타일입니다. 대안은 캐스팅 std::function중이지만 오버 헤드가 있습니다.

의 "학대"를 실제로 생각할 수 없습니다 auto. 내가 상상할 수있는 가장 가까운 것은 중요한 유형으로 명시 적으로 변환하는 것을 박탈하는 것입니다. 그러나 이것을 사용하지 않을 경우 auto원하는 유형의 객체를 생성합니다.

당신이 경우 수있는 부작용을 도입하지 않고 코드에서 일부 중복을 제거, 해야한다 이렇게 좋은.

반례 (다른 사람의 답변에서 차용) :

auto i = SomeClass();
for (auto x = make_unsigned (y); ...)

여기서 우리는 타입이 무엇인지 신경 쓰므로, 우리는 작성 Someclass i;하고for(unsigned x = y;...


해봐 auto코드 작성이 더 쉬운 곳이라면 어디에서나 사용하십시오 .

모든 언어의 모든 새로운 기능은 적어도 일부 유형의 프로그래머가 남용 할 것입니다. 경험이 풍부한 프로그래머 (누가 아님)는 숙련 된 프로그래머가 적당히 남용하여 나머지 숙련 된 프로그래머가 올바른 사용의 경계를 알게됩니다. 과도한 남용은 일반적으로 좋지 않지만 이러한 남용으로 인해 기능이 개선되거나 기능을 대체 할 수 있으므로 더 좋을 수 있습니다.

그러나 내가 몇 줄 이상으로 코드 작업을하고 있다면

auto foo = bla();

where the type is indicated zero times, I might want to change those lines to include types. The first example is great since the type is stated once, and auto saves us from having to write messy templated types twice. Hooray for C++++. But explicitly showing the type zero times, if it's not easily visible in a nearby line, makes me nervous, at least in C++ and its immediate successors. For other languages designed to work at a higher level with more abstraction, polymorphism and genericity, it's fine.


Yes, it can be overused to the detriment of readability. I suggest using it in the contexts where exact types are long, or unutterable, or not important for readability, and variables are short-lived. For example, iterator type usually is long and isn't important, so auto would work:

   for(auto i = container.begin(); i != container.end(); ++i);

auto here doesn't hurt readability.

Another example is parser rule type, which can be long and convoluted. Compare:

   auto spaces = space & space & space;

with

r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&> spaces = 
   space & space & space;

On the other hand, when type is known and is simple, it's much better if it stated explicitly:

int i = foo();

rather than

auto i = foo();

At C++ and Beyond 2012 in the Ask Us Anything panel, there was a fantastic exchange between Andrei Alexandrescu, Scott Meyers and Herb Sutter talking about when to use and not use auto. Skip to minute 25:03 for a 4 minute discussion. All three speakers give excellent points that should be kept in mind for when to not use auto.

I highly encourage people to come to their own conclusion, but my take away was to use auto everywhere unless:

  1. It hurts readability
  2. There is concern about automatic type conversion (e.g. from constructors, assignment, template intermediate types, implicit conversion between integer widths)

Liberal use of explicit helps reduce concern for the latter, which helps minimize the amount of time the former is an issue.

Rephrasing what Herb said, "if you're not doing X, Y, and Z, use auto. Learn what X, Y, and Z are and go forth and use auto everywhere else."


auto can be very dangerous in combination with expression templates which are used a lot by linear algebra libraries such as Eigen or OpenCV.

auto A = Matrix(...);
auto B = Matrix(...);
auto C = A * B; // C is not a matrix. It is a matrix EXPRESSION.
cout << C; // The expression is evaluated and gives the expected result.
... // <code modifying A or B>
cout << C; // The expression is evaluated AGAIN and gives a DIFFERENT result.

Bugs caused by this type of mistakes are a major pain to debug. One possible remedy is to explicitly cast the result to the expected type if you are hellbent on using auto for the left-to-right declaration style.

auto C = Matrix(A * B); // The expression is now evaluated immediately.

I use auto wihout restriction and didn't face any problem. I even sometimes end up using it for simple types like int. This makes c++ a higher level language for me, and allows to declare variable in c++ like in python. After writing python code, I even sometimes write e.g.

auto i = MyClass();

instead of

MyClass i;

This is one case where I would say it is an abuse of the auto keyword.

Often I don't mind what is the exact type of the object, I'm more interested in its fonctionality, and as function names generally say something about the objects they return, auto does not hurt: in e.g. auto s = mycollection.size(), I can guess that s will be a kind of integer, and in the rare case where I care about the exact type, let's check the function prototype then (I mean, I prefer to have to check when I need the info, rather than a priori when code is written, just in case it would be usefull someday, as in int_type s = mycollection.size()).

Concerning this example from the accepted answer:

for ( auto x = max_size; x > 0; --x )

In my code I still use auto in this case, and if I want x to be unsigned, then I use an utility function, named say make_unsigned, which expresses clearly my concerns:

for ( auto x = make_unsigned(max_size); x > 0; --x )

disclaimer: I just describe my use, I'm not competent to give advices!


One of the major problem with C++ program is it allows you to use the uninitialized variable. This leads us to nasty non deterministic program behavior. It should be noted that modern compiler now throw appropriate/message warning messages if program tires to use it.

Just to illustrate this, consider below c++ program:

int main() {
    int x;
    int y = 0;
    y += x;
}

If I compile this program using modern compiler(GCC), it gives the warning. Such warning may not be very obvious if we are working with the real complex production code.

main.cpp: In function 'int main()':

main.cpp:4:8: warning: 'x' is used uninitialized in this function [-Wuninitialized]

y += x;

    ^

================================================================================= Now if we change our program which uses auto, then compile we get the following:

int main() {
    auto x;
    auto y = 0;
    y += x;
}

main.cpp: In function 'int main()':

main.cpp:2:10: error: declaration of 'auto x' has no initializer

 auto x;

      ^

With auto, it is not possible to use the uninitialized variable. This is major advantage which we may get(for free), if we start using auto.

This concept and other great great modern C++ concept is explained by C++ expert Herb Shutter in his CppCon14 talk:

Back to the Basics! Essentials of Modern C++ Style


One danger I have noted is in terms of references. e.g.

MyBigObject& ref_to_big_object= big_object;
auto another_ref = ref_to_big_object; // ?

The problem is another_ref is not actually a reference in this case it is MyBigObject instead of MyBigObject&. You end up copying a big object without realising it.

If you are getting a reference directly from a method you might not think about what it actually is.

auto another_ref = function_returning_ref_to_big_object();

you would need "auto&" or "const auto&"

MyBigObject& ref_to_big_object= big_object;
auto& another_ref = ref_to_big_object;
const auto& yet_another_ref = function_returning_ref_to_big_object();

Use auto where it makes sense for a type to be inferred. If you have something that you know is an integer, or you know it's a string, just use int / std::string, etc. I wouldn't worry about "overusing" a language feature unless it gets to the point of ridiculousness, or obfuscates code.

That's my opinion anyway.


auto keyword can only be used for local variable, not to arguments or class/struct members. So, it is safe and viable to use them anywhere you like. I do use them a lot. The type is deduced at compile time, the debugger shows the type while debugging, the sizeof reports it correctly, the decltype would give correct type - there is no harm. I don't count auto as overused, ever!


TL;DR: See rule-of-thumb at the bottom.

The accepted answer suggests the following rule of thumb:

Use auto whenever it's hard to say how to write the type at first sight, but the type of the right hand side of an expression is obvious.

But I would say that's too restrictive. Sometime I don't care about the types, since the statement is informative enough without me bothering to take the time to figure the type out. What do I mean by that? Consider the example which has popped up in some of the answers:

auto x = f();

What makes this an example of misuse of auto? Is it my ignorance of f()'s return type? Well, it may indeed help if I did know it, but - that's not my main concern. What is much more of a problem is that x and f() are pretty meaningless. If we had:

auto nugget = mine_gold();

instead, then I usually don't care whether the return type of the function is obvious or not. Reading the statement, I know what I'm doing and I know enough about what the return value's semantics to not feel I need to also know its type.

So my answer is: Use auto whenever the compiler allows it, unless:

  • You feel the variable name together with the initialization / assignment expression do not provide enough information about what the statement is doing.
  • You feel the variable name together with the initialization / assignment expression provides "misleading" information about what the type should be - i.e., if you had to guess what comes instead of the auto you would be able to make a guess - and it would be wrong, and this false assumption has repercussions later in the code.
  • You want to force a different type (e.g. a reference).

And also:

  • Prefer giving a meaningful name (which does not contain the type name of course) before replacing auto with the concrete type.

One of my bitter experience with auto is using it with lambda expressions:

auto i = []() { return 0; };
cout<<"i = "<<i<<endl; // output: 1 !!!

Actually, here i is resolved to function pointer of int(*)(). This is just a simple cout, but just imagine what kind of bad compilation / runtime errors it can cause when used with template.

You should avoid auto with such expressions and put a proper return type (or controlled decltype())

Correct usage for above example would be,

auto i = []() { return 0; }(); // and now i contains the result of calling the lambda  

참고URL : https://stackoverflow.com/questions/6434971/how-much-is-too-much-with-c11-auto-keyword

반응형