Initializer list vs. vector

落爺英雄遲暮 提交于 2019-12-20 10:40:27

问题


In C++11, one can use initializer lists to initialize parameters in functions. What is the purpose of it? Can't the same be done with const vectors? What is the difference of the two programs below?

Using an initializer list:

#include <iostream>

using namespace std;

int sumL(initializer_list<int> l){
    int sum = 0;
    for (const auto i: l){
        sum += i;
    }
    return sum;
}

int main(){

    cout << sumL({1, 2, 3}) << "\n";

    return 0;
}

Using a const vector:

#include <iostream>
#include <vector>

using namespace std;

int sumV(const vector<int> l){
    int sum = 0;
    for (const auto i: l){
        sum += i;
    }
    return sum;
}

int main(){

    cout << sumV({1, 2, 3}) << "\n";
    return 0;
}

回答1:


The common use of std::initializer_list is as argument to constructors of container (and similar) classes, allowing convenient initialisation of those containers from a few objects of the same type. Of course, you can use std::initializer_list otherwise and then use the same {} syntax.

Since a std::initializer_list has a fixed size, it doesn't require dynamic allocation and hence can be efficiently implemented. A std::vector, on the other hand, requires dynamic memory allocation. Even in your simple example it is unlikely that the compiler will optimize this overhead away (avoid the intermediary std::vector and its dynamic memory allocation). Other than that, there is no difference in the outcome of your programs (though you should take a const std::vector<int>& argument to avoid a copy and its associated dynamic memory allocation).




回答2:


The semantics of the two are quite different. The initializer_list has pointer semantics while the vector has value semantics.

In your first example, the compiler will generate code similar to the following:

int const __temp_array[3] = {1, 2, 3};
cout << sumL(std::initializer_list<int>(__temp_array, __temp_array + 3)) << "\n";

This is explained in [dcl.init.list]/5. As you can see, within sumL you have access to const pointers to the elements of the braced-init-list, this means you have no other option but to copy the elements out of the list.

In case of sumV you could've std::moved the elements from the vector if needed (assuming the parameter type is not const).

Similarly, copying the initializer_list performs shallow copies, i.e. only the pointers will be copied, while copying the vector, of course, means the elements will be copied.

In your example, none of the points above really make any difference, other than constructing the vector will require dynamic memory allocation, while constructing the initializer_list will not.




回答3:


initializer_list uses optimal storage location and prevents unnecessary calls, it's designed to be lightweight, while with vector there's a heap allocation and there may be more copies/moves made.




回答4:


initalizer_list is not a generalized container like std::vector. It's primary purpose is object initialization. If the low overheard and no heap allocation is attractive to you I'd suggest looking at std::array. It a fixed sized stack allocated array that has all the conveniences of a STL container, which is essentially a thin wrapper on top of a c-array.



来源:https://stackoverflow.com/questions/27753420/initializer-list-vs-vector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!