无法在一个程序中使用 std::size()
Not able to use std::size() in one program
我正在使用数组。所以要找到数组的大小,我需要使用 std::size(),它在一个程序中运行良好但在另一个程序中无法运行。
有效的程序:
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
int array[]{ 30, 50, 20, 10, 40};
std::sort(std::begin(array), std::end(array));
for (int i{0}; i < static_cast<int>(std::size(array)); ++i)
{
std::cout << array[i] << '\t';
}
std::cout << '\n';
return 0;
}
输出:
10 20 30 40 50
无法运行的程序:
#include <iostream>
#include <iterator> // for std::size() but not working yet
void splitInteger(int integer, int components[])
{
int count{0};
do
{
int element{ integer % 10 };
components[count] = element;
integer = integer / 10;
++count;
}
while(integer != 0);
}
int main()
{
int num{};
std::cin >> num;
int components[]{};
splitInteger(num, components);
std::cout << std::size(components) << '\n';
return 0;
}
编译报错如下:
tempCodeRunnerFile.cpp: In function ‘int main()’:
tempCodeRunnerFile.cpp:38:38: error: no matching function for call to ‘size(int [0])’
38 | std::cout << std::size(components) << '\n';
| ^
In file included from /usr/include/c++/9/string:54,
from /usr/include/c++/9/bits/locale_classes.h:40,
from /usr/include/c++/9/bits/ios_base.h:41,
from /usr/include/c++/9/ios:42,
from /usr/include/c++/9/ostream:38,
from /usr/include/c++/9/iostream:39,
from tempCodeRunnerFile.cpp:1:
/usr/include/c++/9/bits/range_access.h:242:5: note: candidate: ‘template<class _Container> constexpr decltype (__cont.size()) std::size(const _Container&)’
242 | size(const _Container& __cont) noexcept(noexcept(__cont.size()))
| ^~~~
/usr/include/c++/9/bits/range_access.h:242:5: note: template argument deduction/substitution failed:
/usr/include/c++/9/bits/range_access.h: In substitution of ‘template<class _Container> constexpr decltype (__cont.size()) std::size(const _Container&) [with _Container = int [0]]’:
tempCodeRunnerFile.cpp:38:38: required from here
/usr/include/c++/9/bits/range_access.h:243:24: error: request for member ‘size’ in ‘__cont’, which is of non-class type ‘const int [0]’
243 | -> decltype(__cont.size())
| ~~~~~~~^~~~
/usr/include/c++/9/bits/range_access.h:252:5: note: candidate: ‘template<class _Tp, long unsigned int _Nm> constexpr std::size_t std::size(const _Tp (&)[_Nm])’
252 | size(const _Tp (&/*__array*/)[_Nm]) noexcept
| ^~~~
/usr/include/c++/9/bits/range_access.h:252:5: note: template argument deduction/substitution failed:
我不知道为什么会这样。任何帮助将不胜感激。
此外,我正在使用带有这些标志的 g++:
g++ -Wall -Weffc++ -Wextra -Wsign-conversion -Werror -std=c++17
首先,这个定义:
int components[]{};
完全错误。如果你真的需要旧的 c 风格数组,你需要使用 new:
来定义它们的大小
int *components = new int[size];
C 风格数组必须在编译期间知道它们的大小,除非您使用关键字 new。
如果您想使用未定义大小(可以修改)的集合,请阅读 std::vector
。当你想找到它的大小时,使用这个调用:
int size_of_v = std::size(v);
第一个代码之所以有效,是因为一个事实——编译器可以判断数组有多大。
假设你只是想要一个答案,而且还想学习一些东西,这里是第一个代码的更“专业”版本:
#include <algorithm>
#include <array>
#include <iostream>
int main()
{
std::array arr = {30, 50, 20, 10, 40};
std::sort(begin(arr), end(arr));
// modern old-fashioned loop, use it if you really need the index
for (int i = 0; i < std::ssize(arr); ++i)
{
std::cout << arr[i] << '\t';
}
// better:
for (auto elem : arr)
{
std::cout << elem << '\t';
}
std::cout << '\n';
return 0;
}
解释:
- 不需要使用 C 风格的数组,我使用
std::array
代替。请注意将它与初始化程序一起使用是多么容易:编译器会根据初始化程序 自动提供 array
元素的类型和数量
- 我更喜欢使用
=
语法初始化简单变量,而无需显式构造函数,例如 int
s。您不必做同样的事情,但许多老朋友会因为您的惯例而分心。就像任何惯例一样,这是一个品味和双方同意的问题。
- 因为我使用的是
std::array
,所以我不必在begin
和end
之前加上std::
,代码变得更简单
- 在第一个循环中,我使用了
std::ssize
,这是 C++20 中引入的一个特性,因此我不需要任何转换:代码再次得到简化
- 但是,如果除了交互之外不需要索引,请选择基于范围的
for
循环,for (auto [const] [&] variable : container)
EXIT_SUCCESS
比 0
更逐字(在 main
中都是多余的)
- 旁注:一些程序员避免在流中使用字符文字,比如 ``\n
\
,因为他们害怕不小心写出像 ``\n\' or \'
\n 这样的东西`',有意想不到的意义(自己试试吧!)。
现在,第二个错误代码。
它真正有趣的部分是:
int components[]{};
在这里声明一个 C 风格的数组(现在您知道这通常不是最好的主意)components
。根据标准,C 样式数组需要在编译时知道它们的大小,尽管许多编译器(如 gcc)具有使此要求无效的扩展。但这里不是这种情况,编译器拥有符合标准所需的所有信息:虽然您留下了空方括号,但您还提供了初始化列表。此列表为空。编译器得出结论,您的意图是这样的:
int components[0];
你的数组有零元素,所以它不需要初始化器,实际上完全没用,不过,这是一个有趣的部分,你可以获取它的地址,在任何使用数组名/指针的表达式中使用它等价,将其用作 sizeof
等的参数。这就是问题的根源。
我正在使用数组。所以要找到数组的大小,我需要使用 std::size(),它在一个程序中运行良好但在另一个程序中无法运行。
有效的程序:
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
int array[]{ 30, 50, 20, 10, 40};
std::sort(std::begin(array), std::end(array));
for (int i{0}; i < static_cast<int>(std::size(array)); ++i)
{
std::cout << array[i] << '\t';
}
std::cout << '\n';
return 0;
}
输出:
10 20 30 40 50
无法运行的程序:
#include <iostream>
#include <iterator> // for std::size() but not working yet
void splitInteger(int integer, int components[])
{
int count{0};
do
{
int element{ integer % 10 };
components[count] = element;
integer = integer / 10;
++count;
}
while(integer != 0);
}
int main()
{
int num{};
std::cin >> num;
int components[]{};
splitInteger(num, components);
std::cout << std::size(components) << '\n';
return 0;
}
编译报错如下:
tempCodeRunnerFile.cpp: In function ‘int main()’:
tempCodeRunnerFile.cpp:38:38: error: no matching function for call to ‘size(int [0])’
38 | std::cout << std::size(components) << '\n';
| ^
In file included from /usr/include/c++/9/string:54,
from /usr/include/c++/9/bits/locale_classes.h:40,
from /usr/include/c++/9/bits/ios_base.h:41,
from /usr/include/c++/9/ios:42,
from /usr/include/c++/9/ostream:38,
from /usr/include/c++/9/iostream:39,
from tempCodeRunnerFile.cpp:1:
/usr/include/c++/9/bits/range_access.h:242:5: note: candidate: ‘template<class _Container> constexpr decltype (__cont.size()) std::size(const _Container&)’
242 | size(const _Container& __cont) noexcept(noexcept(__cont.size()))
| ^~~~
/usr/include/c++/9/bits/range_access.h:242:5: note: template argument deduction/substitution failed:
/usr/include/c++/9/bits/range_access.h: In substitution of ‘template<class _Container> constexpr decltype (__cont.size()) std::size(const _Container&) [with _Container = int [0]]’:
tempCodeRunnerFile.cpp:38:38: required from here
/usr/include/c++/9/bits/range_access.h:243:24: error: request for member ‘size’ in ‘__cont’, which is of non-class type ‘const int [0]’
243 | -> decltype(__cont.size())
| ~~~~~~~^~~~
/usr/include/c++/9/bits/range_access.h:252:5: note: candidate: ‘template<class _Tp, long unsigned int _Nm> constexpr std::size_t std::size(const _Tp (&)[_Nm])’
252 | size(const _Tp (&/*__array*/)[_Nm]) noexcept
| ^~~~
/usr/include/c++/9/bits/range_access.h:252:5: note: template argument deduction/substitution failed:
我不知道为什么会这样。任何帮助将不胜感激。
此外,我正在使用带有这些标志的 g++:
g++ -Wall -Weffc++ -Wextra -Wsign-conversion -Werror -std=c++17
首先,这个定义:
int components[]{};
完全错误。如果你真的需要旧的 c 风格数组,你需要使用 new:
来定义它们的大小int *components = new int[size];
C 风格数组必须在编译期间知道它们的大小,除非您使用关键字 new。
如果您想使用未定义大小(可以修改)的集合,请阅读 std::vector
。当你想找到它的大小时,使用这个调用:
int size_of_v = std::size(v);
第一个代码之所以有效,是因为一个事实——编译器可以判断数组有多大。
假设你只是想要一个答案,而且还想学习一些东西,这里是第一个代码的更“专业”版本:
#include <algorithm>
#include <array>
#include <iostream>
int main()
{
std::array arr = {30, 50, 20, 10, 40};
std::sort(begin(arr), end(arr));
// modern old-fashioned loop, use it if you really need the index
for (int i = 0; i < std::ssize(arr); ++i)
{
std::cout << arr[i] << '\t';
}
// better:
for (auto elem : arr)
{
std::cout << elem << '\t';
}
std::cout << '\n';
return 0;
}
解释:
- 不需要使用 C 风格的数组,我使用
std::array
代替。请注意将它与初始化程序一起使用是多么容易:编译器会根据初始化程序 自动提供 - 我更喜欢使用
=
语法初始化简单变量,而无需显式构造函数,例如int
s。您不必做同样的事情,但许多老朋友会因为您的惯例而分心。就像任何惯例一样,这是一个品味和双方同意的问题。 - 因为我使用的是
std::array
,所以我不必在begin
和end
之前加上std::
,代码变得更简单 - 在第一个循环中,我使用了
std::ssize
,这是 C++20 中引入的一个特性,因此我不需要任何转换:代码再次得到简化 - 但是,如果除了交互之外不需要索引,请选择基于范围的
for
循环,for (auto [const] [&] variable : container)
EXIT_SUCCESS
比0
更逐字(在main
中都是多余的)- 旁注:一些程序员避免在流中使用字符文字,比如 ``\n
\
,因为他们害怕不小心写出像 ``\n\' or \'
\n 这样的东西`',有意想不到的意义(自己试试吧!)。
array
元素的类型和数量
现在,第二个错误代码。
它真正有趣的部分是:
int components[]{};
在这里声明一个 C 风格的数组(现在您知道这通常不是最好的主意)components
。根据标准,C 样式数组需要在编译时知道它们的大小,尽管许多编译器(如 gcc)具有使此要求无效的扩展。但这里不是这种情况,编译器拥有符合标准所需的所有信息:虽然您留下了空方括号,但您还提供了初始化列表。此列表为空。编译器得出结论,您的意图是这样的:
int components[0];
你的数组有零元素,所以它不需要初始化器,实际上完全没用,不过,这是一个有趣的部分,你可以获取它的地址,在任何使用数组名/指针的表达式中使用它等价,将其用作 sizeof
等的参数。这就是问题的根源。