确保以下大型结构的整数初始化为0的最佳方法是什么?
struct Statistics {
int num_queries;
int num_respones;
// ... 97 more counters here
int num_queries_filtered;
}
Run Code Online (Sandbox Code Playgroud)
我想避免必须检查每个地方这个结构初始化,以确保它是初始化值Statistics s();而不是默认初始化Statistics s;.
Statistics s; // Default initialized by accident here
s.num_queries++; // Oh no, this is a bug because it wasn't initialized to zero
Statistics s2{}; // Correctly value initialized
s2.num_queries++; // Successful
Run Code Online (Sandbox Code Playgroud)
建议1 - 使用memset,但这感觉就像一个黑客,我们利用值初始化发生相当于0填充数据结构:
struct Statistics {
Statistics() { memset(this, 0, sizeof(*this)); }
// ... counters here
}
Run Code Online (Sandbox Code Playgroud)
建议2 - 使用构造函数初始化列表,但这很麻烦,当人们将来添加新计数器时,他们可能忘记在构造函数中对它们进行零初始化:
struct Statistics {
Statistics() : num_queries(0), num_respones(0), /* ... */, num_queries_filtered(0) {}
// ... counters here
}
Run Code Online (Sandbox Code Playgroud)
建议3 - 强制值初始化发生如下:
struct StatisticsUnsafe {
// ... counters here
}
struct Statistics : public StatisticsUnsafe {
Statistics() : StatisticsUnsafe() {}
}
Run Code Online (Sandbox Code Playgroud)
你觉得最好的方法是什么?你有其他选择吗?
编辑我想澄清一下,在我的实际代码中,每个计数器都有一个有意义的名称,例如"num_queries_received","num_responses"等.这就是为什么我不选择使用"计数器"形式的向量或数组的原因[100]"
EDIT2将示例更改Statistics s2();为Statistics s2{};
从C++ 11开始,您还可以:
struct Statistics {
int counter1 = 0;
int counter2 = 0;
// ... more counters here
int counter100 = 0;
};
Run Code Online (Sandbox Code Playgroud)
除非你有一个相当具体的理由否则,你的第一选择应该是std::vector,例如:
std::vector<int> Statistics(100);
Run Code Online (Sandbox Code Playgroud)
这将自动归零所有内容.您可以counter将数组中的个人称为:
++Statistics[40];
Run Code Online (Sandbox Code Playgroud)
...这将递增41 日项目(第一个是Statistics[0]).
如果大小确实固定为100(或者您在编译时知道的其他数字),您可能更愿意使用std::array:
std::array<int, 100> Statistics;
Run Code Online (Sandbox Code Playgroud)
这可能是一个快一点,通常采用的是(小)更少的内存,但固定尺寸(而用的std::vector,你可以使用push_back,erase等等,添加和删除的项目).
鉴于编辑过的问题(对象真的不像数组一样),我可能会考虑一些不同的东西,可能是这样的:
template <class T>
class inited {
T val;
public:
inited(T val=T()) : val(val) {}
operator T() const { return val; }
operator=(T const &newval) { val = new_val; }
};
struct Statistics {
inited<int> sum;
inited<int> count;
inited<double> mean;
};
Run Code Online (Sandbox Code Playgroud)
然后a inited<T>总是被初始化为某个值 - 如果你愿意,你可以指定一个值,如果你没有指定任何值,它使用值初始化(对于算术类型将给出零,对于指针类型给出空指针,或者对定义一个的类型使用默认构造函数.
既然它定义了一个operator T和一个operator=,你仍然可以像往常一样分配给元素/从元素中分配:
Statistics.sum = 100;
Statistics.count = 2;
Statistics.mean = static_cast<double>(Statistics.sum) / Statistics.count;
Run Code Online (Sandbox Code Playgroud)
您可能更喜欢使用单个:
operator T&() { return val; }
Run Code Online (Sandbox Code Playgroud)
相反.这既支持读取和写入(如上所述),也支持复合赋值运算符(例如,+=和-=).
| 归档时间: |
|
| 查看次数: |
452 次 |
| 最近记录: |