Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

c++20 - C++ - std::initializer_list vs std::span

What is the difference between std::initializer_list and std::span? Both are contiguous sequences of values of some type. Both are non-owning. So when do we use the first and when do we use the latter?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The short answer is that std::initializer_list<T> is used to create a new range, for the purposes of initialization. While std::span<T> is used to refer to existing ranges, for better APIs.


std::initializer_list<T> is a language feature that actually constructs a new array and owns it. It solves the problem of how to conveniently initialize containers:

template <typename T>
struct vector {
    vector(std::initializer_list<T>);
};

vector<int> v = {1, 2, 3, 4};

That creates a std::initializer_list<int> on the fly containing the four integers there, and passes it into vector so that it can construct itself properly.

This is really the only place std::initializer_list<T> should be used: either constructors or function parameters to pass a range in on the fly, for convenience (unit tests are a common place that desires such convenience).


std::span<T> on the other hand is used to refer to an existing range. Its job is to replace functions of the form:

void do_something(int*, size_t);

with

void do_something(std::span<int>);

Which makes such functions generally easier to use and safer. std::span is constructible from any appropriate contiguous range, so taking our example from earlier:

std::vector<int> v = {1, 2, 3, 4};
do_something(v); // ok

It can also be used to replace functions of the form:

void do_something_else(std::vector<unsigned char> const&);

Which can only be called with, specifically, a vector, with the more general:

void do_something_else(std::span<unsigned char const>);

Which can be called with any backing contiguous storage over unsigned char.

With span you have to be careful, since it's basically a reference that just doesn't get spelled with a &, but it is an extremely useful type.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...