C++ 在多维数组中设置默认值的更优雅方式
C++ More Elegant Way to set Default Values in multi-dimensional array
在我的 .h 文件中,我有:
struct tup{
tup() :
token{{-1,"a","b","c","d","e","f"},
{-1,"a","b","c","d","e","f"},
...
{-1,"a","b","c","d","e","f"}} {}
struct {
int pos;
std::string nj, ny, pa, ri, ct, fl;
} token[100];
其中“...”指的是多 97 行相同类型的代码。有没有更优雅的方式来为我的令牌设置默认值?
如果您愿意使用 std::vector
而不是数组,您可以使用:
struct tup{
tup() : tokens(100, {-1,"a","b","c","d","e","f"}) {}
struct token {
int pos;
std::string nj, ny, pa, ri, ct, fl;
};
std::vector<token> tokens;
};
这是一个演示程序,展示了如果您的编译器支持 C++ 2014,则如何定义构造函数。否则,您必须将类型 std::remove_extent_t
更改为 C++ 2011 中的等效类型。
#include <iostream>
#include <algorithm>
#include <iterator>
#include <type_traits>
#include <string>
struct tup{
tup()
{
std::fill( std::begin( token ), std::end( token ),
std::remove_extent_t<decltype( token )>( {-1,"a","b","c","d","e","f"} ) );
}
struct {
int pos;
std::string nj, ny, pa, ri, ct, fl;
} token[100];
};
int main()
{
tup tup;
std::cout << tup.token[0].pos << ' ' << tup.token[0].nj << std::endl;
std::cout << "//..." << std::endl;
std::cout << tup.token[99].pos << ' ' << tup.token[99].nj << std::endl;
}
程序输出是
-1 a
//...
-1 a
在任何情况下,您都可以使用我展示的标准算法 std::fill
或其他方式,例如使用 lambda 表达式。
您应该在 cpp 文件中使用构造函数(和 classes 而不是结构)。数组的实际内容是不应该在 header 中的实现细节。
最好的方法是在初始化 class 的方法中使用循环(100 项对于计算机来说是一个很小的数字,您看不出有什么区别)。它还允许您更好地处理错误(构造函数不能轻易 return 错误代码;您可以为此使用引用或成员,但它很丑陋)。这是我能想到的最好的方法。
在你的解析器中,所有的字符串都是字符吗?如果 n 是您的字符串的最大大小,您可以简单地使用 char 或 char[n+1] 。使用 std::strings,您可以对小尺寸进行静态分配(浪费一点 space),对较大尺寸进行动态分配。如果您必须处理分配错误,那么您需要一个用于初始化 class 的成员。因此,header 将只提供其他文件所需的最少信息(结构和大小,而不是数据)。
如果你希望以后能够阅读你的代码,我也建议你使用有意义的变量名(它们的大小不是问题)。
100 的限制在我看来像是代码的味道。为什么不使用动态分配和不受限制的大小?您可以在构建它们时简单地将新令牌值推送到 collection 中。默认值应该只在令牌的构造函数中,而不是在具有虚拟大小的数组中。如果稍后扩展解析器以处理更多标记怎么办? hard-coded 如果您希望代码不断发展,数组的最大值是一种不好的做法。当您达到限制时,您通常会在发现错误之前遇到错误。
在我的 .h 文件中,我有:
struct tup{
tup() :
token{{-1,"a","b","c","d","e","f"},
{-1,"a","b","c","d","e","f"},
...
{-1,"a","b","c","d","e","f"}} {}
struct {
int pos;
std::string nj, ny, pa, ri, ct, fl;
} token[100];
其中“...”指的是多 97 行相同类型的代码。有没有更优雅的方式来为我的令牌设置默认值?
如果您愿意使用 std::vector
而不是数组,您可以使用:
struct tup{
tup() : tokens(100, {-1,"a","b","c","d","e","f"}) {}
struct token {
int pos;
std::string nj, ny, pa, ri, ct, fl;
};
std::vector<token> tokens;
};
这是一个演示程序,展示了如果您的编译器支持 C++ 2014,则如何定义构造函数。否则,您必须将类型 std::remove_extent_t
更改为 C++ 2011 中的等效类型。
#include <iostream>
#include <algorithm>
#include <iterator>
#include <type_traits>
#include <string>
struct tup{
tup()
{
std::fill( std::begin( token ), std::end( token ),
std::remove_extent_t<decltype( token )>( {-1,"a","b","c","d","e","f"} ) );
}
struct {
int pos;
std::string nj, ny, pa, ri, ct, fl;
} token[100];
};
int main()
{
tup tup;
std::cout << tup.token[0].pos << ' ' << tup.token[0].nj << std::endl;
std::cout << "//..." << std::endl;
std::cout << tup.token[99].pos << ' ' << tup.token[99].nj << std::endl;
}
程序输出是
-1 a
//...
-1 a
在任何情况下,您都可以使用我展示的标准算法 std::fill
或其他方式,例如使用 lambda 表达式。
您应该在 cpp 文件中使用构造函数(和 classes 而不是结构)。数组的实际内容是不应该在 header 中的实现细节。 最好的方法是在初始化 class 的方法中使用循环(100 项对于计算机来说是一个很小的数字,您看不出有什么区别)。它还允许您更好地处理错误(构造函数不能轻易 return 错误代码;您可以为此使用引用或成员,但它很丑陋)。这是我能想到的最好的方法。
在你的解析器中,所有的字符串都是字符吗?如果 n 是您的字符串的最大大小,您可以简单地使用 char 或 char[n+1] 。使用 std::strings,您可以对小尺寸进行静态分配(浪费一点 space),对较大尺寸进行动态分配。如果您必须处理分配错误,那么您需要一个用于初始化 class 的成员。因此,header 将只提供其他文件所需的最少信息(结构和大小,而不是数据)。
如果你希望以后能够阅读你的代码,我也建议你使用有意义的变量名(它们的大小不是问题)。
100 的限制在我看来像是代码的味道。为什么不使用动态分配和不受限制的大小?您可以在构建它们时简单地将新令牌值推送到 collection 中。默认值应该只在令牌的构造函数中,而不是在具有虚拟大小的数组中。如果稍后扩展解析器以处理更多标记怎么办? hard-coded 如果您希望代码不断发展,数组的最大值是一种不好的做法。当您达到限制时,您通常会在发现错误之前遇到错误。