为什么按值传递的数组上的 std::size 不起作用?
Why does the std::size on an array passed by value do not work?
为什么 std::size()
对按值传递的静态分配数组不起作用?
void print_elemTab(int tab[])
{
// ...
int size = std::size(tab); //error
// ...
}
void test_tab()
{
const int TAB_SIZE = 5;
int tab[TAB_SIZE] = {};
// ...
cout << std::size(tab) << std::endl; //print 5
print_elemTab(tab);
// ...
}
我正在打印尺寸,然后在我再次使用 std::size()
的子函数 print_elemTab()
中传递 tab
。
我收到 no matching function 错误,所以我想知道为什么 std::size()
第一次在 test_tab()
而不是 print_elemTab()
我必须通过引用传递吗?那么除了任意长度的数组,我该怎么做呢?
或者我是否因为某些我不知道的事情而必须以其他方式制作它?
是的,您必须通过引用传递它,因为在将它传递给您的函数时它已衰减为指针。并使函数接受任何大小我建议使用函数模板如下
#include <iostream>
template<size_t n>
void print_elemTab(int (&tab)[n])
{
int size = std::size(tab);
std::cout << size << "\n";// or just std::cout << n; and ignore the previous line
}
void test_tab() {
const int TAB_SIZE = 5;
int tab[TAB_SIZE] = {};
std::cout << std::size(tab) << std::endl; //print 5
print_elemTab(tab);
}
int main(){
test_tab();
}
Do I have to pass it by reference? And so how do I make it but for any
array of any length?
是,通过引用传递它是一种选择。
template<std::size_t n>
void print_elemTab(int (&tab)[N]) // const int (&tab)[N], if the elements won't be modified
{
std::cout << N << "\n"; // where you can directly get the size `N`
}
或者像下面这样的简单模板函数
template<typename T>
void print_elemTab(T& tab)// const T& tab, if the elements won't be modified
{
const auto size = std::size(tab);
std::cout << size << "\n";
}
另一种选择是将数组推导为其实际类型。在您的例子中,tab
的类型为 int[5]
。如果您通过模板函数perfectly forward,编译器可以推断出其实际类型(除了衰减为指针)。
#include <iostream>
#include <array>
template<typename T>
void print_elemTab(T&& tab)
{
const auto size = std::size(tab); // now you can do std::size() on the int[size]
std::cout << size << "\n";
}
表达式中使用的数组指示符被隐式转换为指向其第一个元素的指针(极少数例外,例如在 sizeof
运算符中使用它们)。
所以在这次通话中
print_elemTab(tab);
参数表达式的类型为 int *
。
另一方面,具有数组类型的函数参数被编译器调整为指向数组元素类型的指针。
例如这些函数声明
void print_elemTab(int tab[]);
void print_elemTab(int tab[5]);
void print_elemTab(int tab[100]);
声明同一个函数,等同于下面的声明
void print_elemTab(int *tab);
您甚至可以在您的程序中包含所有这些声明,尽管编译器会发出一条消息指出存在冗余声明。
因此在函数中,您正在处理 int *
类型的指针。 sizeof( int * )
通常等于 4
或 8
,具体取决于所使用的系统。
如果您有这样的声明,您应该更改它,指定第二个参数,该参数将保持传递的数组中的元素数量,如
void print_elemTab(int *tab, size_t n );
而且函数可以这样调用
print_elemTab(tab, std::size( tab ) );
另一种方法是通过引用传递数组。在这种情况下,您应该声明一个模板函数,例如
template <size_t N>
void print_elemTab( int ( &tab )[N] );
在函数中,您可以直接使用模板参数 N
作为数组中元素的数量。或者您可以将相同的标准 C++ 函数 std::size
应用于数组。
或者可以使用第二个模板类型参数来更通用地声明函数,例如
template <typename T, size_t N>
void print_elemTab( T ( &tab )[N] );
另一种方法是像这样声明函数
template <typename Container>
void print_elemTab( Container &container );
在这种情况下,您还可以将标准函数 std::size
应用于参数容器。
为什么 std::size()
对按值传递的静态分配数组不起作用?
void print_elemTab(int tab[])
{
// ...
int size = std::size(tab); //error
// ...
}
void test_tab()
{
const int TAB_SIZE = 5;
int tab[TAB_SIZE] = {};
// ...
cout << std::size(tab) << std::endl; //print 5
print_elemTab(tab);
// ...
}
我正在打印尺寸,然后在我再次使用 std::size()
的子函数 print_elemTab()
中传递 tab
。
我收到 no matching function 错误,所以我想知道为什么 std::size()
第一次在 test_tab()
而不是 print_elemTab()
我必须通过引用传递吗?那么除了任意长度的数组,我该怎么做呢?
或者我是否因为某些我不知道的事情而必须以其他方式制作它?
是的,您必须通过引用传递它,因为在将它传递给您的函数时它已衰减为指针。并使函数接受任何大小我建议使用函数模板如下
#include <iostream>
template<size_t n>
void print_elemTab(int (&tab)[n])
{
int size = std::size(tab);
std::cout << size << "\n";// or just std::cout << n; and ignore the previous line
}
void test_tab() {
const int TAB_SIZE = 5;
int tab[TAB_SIZE] = {};
std::cout << std::size(tab) << std::endl; //print 5
print_elemTab(tab);
}
int main(){
test_tab();
}
Do I have to pass it by reference? And so how do I make it but for any array of any length?
是,通过引用传递它是一种选择。
template<std::size_t n>
void print_elemTab(int (&tab)[N]) // const int (&tab)[N], if the elements won't be modified
{
std::cout << N << "\n"; // where you can directly get the size `N`
}
或者像下面这样的简单模板函数
template<typename T>
void print_elemTab(T& tab)// const T& tab, if the elements won't be modified
{
const auto size = std::size(tab);
std::cout << size << "\n";
}
另一种选择是将数组推导为其实际类型。在您的例子中,tab
的类型为 int[5]
。如果您通过模板函数perfectly forward,编译器可以推断出其实际类型(除了衰减为指针)。
#include <iostream>
#include <array>
template<typename T>
void print_elemTab(T&& tab)
{
const auto size = std::size(tab); // now you can do std::size() on the int[size]
std::cout << size << "\n";
}
表达式中使用的数组指示符被隐式转换为指向其第一个元素的指针(极少数例外,例如在 sizeof
运算符中使用它们)。
所以在这次通话中
print_elemTab(tab);
参数表达式的类型为 int *
。
另一方面,具有数组类型的函数参数被编译器调整为指向数组元素类型的指针。
例如这些函数声明
void print_elemTab(int tab[]);
void print_elemTab(int tab[5]);
void print_elemTab(int tab[100]);
声明同一个函数,等同于下面的声明
void print_elemTab(int *tab);
您甚至可以在您的程序中包含所有这些声明,尽管编译器会发出一条消息指出存在冗余声明。
因此在函数中,您正在处理 int *
类型的指针。 sizeof( int * )
通常等于 4
或 8
,具体取决于所使用的系统。
如果您有这样的声明,您应该更改它,指定第二个参数,该参数将保持传递的数组中的元素数量,如
void print_elemTab(int *tab, size_t n );
而且函数可以这样调用
print_elemTab(tab, std::size( tab ) );
另一种方法是通过引用传递数组。在这种情况下,您应该声明一个模板函数,例如
template <size_t N>
void print_elemTab( int ( &tab )[N] );
在函数中,您可以直接使用模板参数 N
作为数组中元素的数量。或者您可以将相同的标准 C++ 函数 std::size
应用于数组。
或者可以使用第二个模板类型参数来更通用地声明函数,例如
template <typename T, size_t N>
void print_elemTab( T ( &tab )[N] );
另一种方法是像这样声明函数
template <typename Container>
void print_elemTab( Container &container );
在这种情况下,您还可以将标准函数 std::size
应用于参数容器。