Const *成员变量初始化c++
const * const * member variable initialization c++
我在初始化这个结构体时遇到了麻烦(例如简化)
struct S{ const float * const * const data;};
基本上,我有一个浮点缓冲区的缓冲区,我使用const来确保使用S的人不能改变这个成员的任何内容(只读)。
我的问题是,这是复杂的,难以阅读初始化,我想使用一个lambda返回一个const S,所以我可以初始化成员在我的lambda写成员名:s.data = ptr;
现在这段代码很复杂,我想知道有什么更好的解决方案。
当然,有struct S{float ** data;}
和const S
不能有效地保护成员的内容,我不能修改S::data
,但我可以修改*S::data
。
我该怎么办?
Thank you
为什么不直接删除最后一个const
呢?
struct S{ const float * const * data;};
这样,你可以初始化data
,但它仍然不能用来修改任何指向的东西。
data
本身是可以修改的,但是如果不允许的话,它应该是private
。
推荐的方法是给S
添加一个构造函数。这允许你在函数初始化列表中设置data的值。
struct S
{
explicit S(const float *const *const d) : data(d) {}
const float * const * const data;
};
S GetS()
{
float **data = GetData();
return S(data);
}
如果你想限制谁可以在S::data
初始化后修改它,你可以框成员变量并使用friendship来允许访问。这需要将data
成员封装在提供转换和赋值操作符的附加结构体中。
struct Outer
{
struct S
{
private:
struct ConstBox
{
friend Outer;
ConstBox(const ConstBox& other) : data_(other.data_) {}
explicit ConstBox(const float *const *const data) : data_(data) {}
operator const float* const* () const { return data_; }
private:
ConstBox& operator=(const float * const * data)
{
data_ = data;
return *this;
}
const float * const * data_;
};
public:
S() : data(nullptr) {}
explicit S(const float *const *const d) : data(d) {}
ConstBox data;
};
S DoSomething() const
{
S s(nullptr);
auto f = []() -> S
{
S s;
s.data = new float*[10];
return s;
};
return f();
}
};
typedef Outer::S S;
void FailTest()
{
S s;
s.data = nullptr; // <-- fails
float** v1 = s.data; // <-- fails
const float** v1 = s.data; // <-- fails
// These are ok
const float* const* v2 = s.data;
}
@CaptainObvious的答案是正确的。为S编写一个构造函数,接受它需要的任何参数,并使用成员初始化器而不是赋值语句来设置'data'。
对于您的简化示例,我将简单地做:
struct S{ float const * const * const data;};
auto create_buffer() -> float const * const * {
float **buf;
/* ... compute buffer contents */
return buf;
}
S s {create_buffer()};
但是,您在评论中提到您有许多成员,并且根据顺序初始化成员不够清楚。
struct S { const A a; const B b; const C c; };
S s {x,y,z}; // order based, not readable enough.
const
成员必须作为对象构造的一部分初始化。必须在初始化器中以某种方式指定它们,或者必须在类中设置它们的值,以便在构造时设置它们。
解决方案1
在构造过程中传递它们的一种方法是使用第二个对象来帮助初始化,但以可读的方式:
struct S_initializer { A a; B b; C c; }
struct S {
const A a; const B b; const C c;
S(S_initializer &s) : a(s.a), b(s.b), c(s.c) {}
};
S make_S() {
S_initializer s;
s.a = x;
s.b = y;
s.c = z;
return S{s};
}
上面涉及一些重复,您可以通过将初始化助手对象设置为S的const成员来避免重复:
struct S {
const S_initializer m;
S(S_initializer &s) : m{s} {}
};
S make_S() {
S_initializer s;
s.a = x;
s.b = y;
s.c = z;
return S{s};
}
权衡的是,现在要访问S的成员,你必须在那里有一个额外的.m
:
A a = s.m.a; // versus just s.a;
解决方案2
第二个方法依赖于编译器扩展;虽然不是标准的c++,但gcc和clang在c++中实现了C99指定初始化式。vc++没有实现这个
S s { .a = x, .b = y, .c = z };
- 是否可以初始化不可复制类型的成员变量(或基类)
- C++使用整数的压缩数组初始化对象
- C++初始化基类
- 多成员Constexpr结构初始化
- 复制列表初始化的隐式转换的等级是多少
- 内联映射初始化的动态atexit析构函数崩溃
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 没有用于初始化C++中的变量模板的匹配构造函数
- 在未初始化映射的情况下,将值插入到映射的映射中
- C++成员初始化
- 为什么在C++中首先初始化成员类
- 同时具有"聚合初始化"和"模板推导"
- 初始化具有非默认构造函数的std::数组项的更好方法
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 在C和C++中初始化结构中的数组
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 在函数内部的声明中初始化数组,并在外部使用它
- 继承:构造函数,初始化C++11中基类的类C数组成员