📅  最后修改于: 2023-12-03 14:59:48.399000             🧑  作者: Mango
在 C++ 中,列表和转发列表可以用于函数调用、初始化和赋值等。它们提供了一种更加便捷简洁的写法,同时也可以避免由于参数类型不匹配等原因导致的编译错误。
列表初始化和转发列表初始化都是 C++11 引入的特性,具体可以参考 cppreference。
列表初始化使用花括号 {}
将参数包含起来,例如:
int arr[] = {1, 2, 3}; // 初始化数组
std::vector<int> v = {1, 2, 3}; // 初始化 vector
std::map<std::string, int> m = {{"a", 1}, {"b", 2}}; // 初始化 map
需要注意的是,如果列表初始化的参数类型与指定类型不匹配,编译器将会报错,例如:
int n = {}; // error: narrowing conversion of '{}' from 'std::initializer_list<int>' to 'int' inside { } [-Wnarrowing]
转发列表初始化使用圆括号 ()
将参数包含起来,例如:
template<typename T>
void foo(T t) {}
foo(1); // 普通函数调用
foo(std::vector<int>{1, 2, 3}); // 转发列表初始化
需要注意的是,转发列表初始化只能传递参数,不能进行运算,例如:
foo(std::vector<int>(1, 2, 3)); // error: no matching function for call to 'std::vector<int>(int, int, int)'
转发列表可以用来在函数调用时转发可变数量的参数,它可以用于任何接受可变数量参数的函数,例如:
template<typename... Args>
void foo(Args&&... args) {}
foo(1, 2, 3); // 使用转发列表转发参数
在上面的例子中,Args
是一个参数包,可以接受任意数量的参数。Args&&... args
中的 &&
表示接受左右值引用,...
表示展开参数包。可以通过 sizeof...(Args)
获取参数包中参数的数量。
转发列表除了可以用于转发参数以外,还可以用于实现完美转发,即保证传递参数的引用类型和值类型一致,例如:
template<typename T>
void foo(T&& t) {}
int n = 1;
foo(n); // 将 n 的值转发给 foo
foo(std::move(n)); // 将 n 的右值引用转发给 foo
在上面的例子中,T&& t
表示将参数类型推导为右值引用或左值引用,可以同时接受值类型和引用类型的参数(即完美转发)。
#include <iostream>
#include <vector>
#include <map>
template<typename... Args>
void foo(Args&&... args) {
std::cout << sizeof...(Args) << std::endl;
}
template<typename T>
void bar(T&& t) {}
int main() {
int arr[] = {1, 2, 3}; // 初始化数组
std::vector<int> v = {1, 2, 3}; // 初始化 vector
std::map<std::string, int> m = {{"a", 1}, {"b", 2}}; // 初始化 map
foo(1, 2, 3); // 使用转发列表转发参数
foo(arr[0], arr[1], arr[2]); // 使用转发列表转发参数
foo(v.begin(), v.end()); // 使用转发列表转发参数
foo(m.begin(), m.end()); // 使用转发列表转发参数
int n = 1;
bar(n); // 将 n 的值转发给 bar
bar(std::move(n)); // 将 n 的右值引用转发给 bar
return 0;
}