C++14中的auto特征

Here's the original LINK: https://solarianprogrammer.com/2014/08/21/cpp-14-auto-tutorial/


The C++14 standard was recently approved. Without bringing big changes to the language, like the previous standard did, the C++14 standard aims to make the programmer’s job easier by improving the C++11 standard.

C++11 introduced the auto keyword (technically auto was present even in the C++03 standard, however C++11 changed the meaning of auto), auto was meant to make the code cleaner and less error prone, by letting you write for example:

1
2
    auto i = 1;
    auto c = return_a_complex_number();

instead of:

1
2
    int i = 1;
    std::complex<double> c = return_a_complex_number();

The type of a variable declared as auto is deduced at compile time, and not at runtime, so using auto does not incur any speed penalty. This means that using auto with an uninitialized variable will rise an error, because the compiler has no way to know the type of the variable:

1
    auto i;		// this will rise a compilation error

An inconsistency of the C++11 standard was that you weren’t allowed to use auto for the type of a function. This has changed in the new standard, for e.g. now you can write:

1
2
3
4
5
    // Error in C++11, works in C++14
    auto my_function() {
        ...
        return value;
    }

as long as your functions returns a value, the compiler knows how to interpret the auto keyword.

At the time of writing this article, you can use C++14 with the latest version of Clang and GCC. For e.g., to compile a C++ code with GCC you could use:

1
    g++-4.9.1 -Wall -std=c++14 -pedantic my_prog_name.cpp -o my_prog_name

To better exemplify the way auto can simplify your code, let’s implement a piece of code in C++98, C++11 and C++14. Say that you want, for example, to modify the values of a vector by applying two functions in the same instruction, something like:

1
    multiply_by_two(add_one(my_vector));	

Obviously, you could write a single function, instead of two, to add one and multiply by two the elements of a vector, the point here is not to write the most performant code, but to illustrate the syntax simplifications allowed by auto.

The C++98 version of multiply_by_two and add_one can be written as:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    std::vector<int>& add_one(std::vector<int> &v) {
        for(std::vector<int>::iterator it = v.begin(); it != v.end(); it++) {
            *it += 1;
        }
        return v;
    }
    
    void multiply_by_two(std::vector<int> &v) {
        for(std::vector<int>::iterator it = v.begin(); it != v.end(); it++) {
            *it *= 2;
        }
    }

The above code is quite verbose for what it does.

Let’s see the C++11 version:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    std::vector<int>& add_one(std::vector<int> &v) {
        for(auto& it : v) {
            it += 1;
        }
        return v;
    }

    void multiply_by_two(std::vector<int> &v) {
        for(auto& it : v) {
            it *= 2;
        }    
    }

The C++11 version is clearly an improvement, we were able to shorten a bit the code using auto and a for range loop. But the code is still verbose.

In C++14 we can use auto for a function type. The above code can be further simplified to:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    auto& add_one(std::vector<int>& v) {
        for(auto& it : v) {
            it += 1;
        }
        return v;
    }

    void multiply_by_two(std::vector<int>& v) {
        for(auto& it : v) {
            it *= 2;
        }    
    }

The C++14 code is shorter, easier to read and more general than the C++11 version. Here is complete code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    // C++14 "auto" demo code	
    #include <iostream>
    #include <vector>

    auto& add_one(std::vector<int>& v) {
        for(auto& it : v) {
            it += 1;
        }
        return v;
    }

    void multiply_by_two(std::vector<int>& v) {
        for(auto& it : v) {
            it *= 2;
        }    
    }

    void print_vec(const std::vector<int>& v) {
        for(const auto& e: v) {
            std::cout << e << std::endl;
        }   
        std::cout << std::endl;     
    }

    int main() {
        // Add one and multiply by two a vector of integers
        std::vector<int> my_vector{-1, 2, 3, 5};
        multiply_by_two(add_one(my_vector));    
        print_vec(my_vector);

        return 0;
    }

If you are tempted to use auto for declaring the type of the vectors from the main function don’t, auto paired with an initializer list (the {} syntax) defines a std::initializer_list which is a different than std::vector.

G++ 4.9.1 also supports unconstrained generic functions, basically you can use auto in a function parameter list, so the above code can be further simplified as :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    auto& add_one(auto& v) {
        for(auto& it : v) {
            it += 1;
        }
        return v;
    }

    void multiply_by_two(auto& v) {
        for(auto& it : v) {
            it *= 2;
        }    
    }

unfortunately, this didn’t entered in the final C++14 standard. It is expected to be added later to the standard as a technical report.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值