这部分是关于风格和正确性的问题。提交以下样例(一个处理包含嵌入头文件数据块的类的简化版本):
首先,技术上的正确性...按照写法,
风格问题...混合这两种初始化方式是不好的风格吗?我的方法是,成员初始化列表中的项目(
class Foo {
public:
Foo(size_t size)
: scratch_(new uint8_t[header_length_ + size]),
size_(header_length_ + size) {
}
~Foo() {
delete[] scratch_;
}
Foo(const Foo&) = delete; // Effective C++
void operator=(const Foo&) = delete; // Effective C++
protected:
struct Header {
uint32_t a, b, c, d;
};
uint8_t * const scratch_;
size_t const size_;
Header * const header_ = reinterpret_cast<Header *>(scratch_);
static constexpr size_t header_length_ = sizeof(Header);
static constexpr size_t data_offset_ = header_length_;
size_t const data_length_ = size_ - data_offset_;
};
首先,技术上的正确性...按照写法,
scratch_
和size_
会被先初始化,然后是header_
,最后是data_length_
吗?(constexpr
项目是编译时字面常量,不参与初始化顺序。)同样正确的是,初始化程序如何声明,无论是默认成员初始化(int foo = 5
)还是成员初始化列表,都不会影响初始化顺序,而是成员声明的顺序才是重要的吗?我在这个答案中找到了有关初始化顺序的ISO规范,并且我所了解的是,scratch_
和size_
出现在成员初始化列表中与给定默认成员初始化器的其他成员相比并不重要;唯一重要的是scratch_
和size_
在其他成员之前声明。假设如果scratch_
和size_
是最后声明的,则header_
和data_length_
将(不希望/不正确地)首先初始化。风格问题...混合这两种初始化方式是不好的风格吗?我的方法是,成员初始化列表中的项目(
scratch_
,size_
)取决于传递给构造函数的参数,而其余类成员则来自其他类成员。显然,如果初始化程序依赖于构造函数参数,则必须将其放入成员初始化列表中。我是否应该将所有初始化程序都放入成员初始化列表中,并放弃默认成员初始化器?在我看来,这可能会使代码变得更难以理解。您有何想法?
delete[] scratch_;
。 - Igor Tandetnik