const * const *成员变量初始化c ++

时间:2013-05-21 22:47:06

标签: c++ c++11

我在初始化这个结构时遇到了麻烦(例如简化)

struct S{ const float * const * const data;};

基本上我有一个浮点缓冲区缓冲区,我使用const来确保使用S的人不能改变这个成员的任何东西(只读)。

我的问题是这很复杂,难以初始化,我想使用返回const S的lambda,因此我可以通过编写成员名称来初始化lambda中的成员:s.data = ptr;

现在这段代码很复杂,我想知道什么是更好的解决方案。

AFAIK,struct S{float ** data;}一个const S无法有效保护会员的内容,我无法修改S::data,但我可以修改*S::data

我该怎么办?

谢谢

4 个答案:

答案 0 :(得分:3)

为什么不删除最后一个const

struct S{ const float * const * data;};

这样你可以随意初始化data,但它仍然无法用于修改指向的任何内容。

data本身可以修改,但如果要防止它,它应该只是private

答案 1 :(得分:1)

推荐的方法是向S添加构造函数。这允许您在ctor初始化列表中设置数据的值。

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,您可以成员变量并使用友谊来允许访问。这需要将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;
}

答案 2 :(得分:0)

@ CaptainObvious的答案是正确的。为S编写一个构造函数,获取它需要的任何参数,并使用成员初始化而不是赋值语句来设置'data'。

答案 3 :(得分:0)

通过简化示例,我只会这样做:

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 };