首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >像数组一样访问成员?

像数组一样访问成员?
EN

Stack Overflow用户
提问于 2015-08-15 09:23:19
回答 2查看 121关注 0票数 2

由于阅读了很多警告不要使用这样的工会:

代码语言:javascript
复制
union rgba
{
    struct
    {
        uint8_t r, g, b, a;
    } components;
    uint8_t index[4];
    uint32_t value;
};

因为这是未定义的行为,所以我决定保持简单,如下所示:

代码语言:javascript
复制
struct rgba
{
    uint8_t r, g, b, a;
};

但是,有时我确实需要使用索引在一个循环中访问rgba,否则我必须分别为每个组件复制相当长的代码。

所以我想出了这个:

代码语言:javascript
复制
struct rgba
{
    u8 r, g, b, a;

    constexpr u8& operator[](size_t x)
    {
        return const_cast<u8*>(&r)[x];
    }
};

这依赖于这样的假设:rgba以线性方式放置在内存中,中间没有隐藏的样板,编译器保留可变顺序。

这样,我就可以像我想要的那样访问组件:

代码语言:javascript
复制
rgba c;
for (int i = 0; i < 3; i++)
    c[i] = i ^ (i + 7);
c.a = 0xFF;
  1. 因为我做了相当大的假设,我很确定这是比使用联合进行类型双关更多的未定义的行为。我说的对吗?
  2. 否则我如何实现类似的设计?
    1. 如果可能的话,我想避免写c.r() = 5,因为它看起来很有趣。
    2. c.components[RED]这样的访问器使用宏,我喜欢避免宏。
    3. 如果考虑到访问这种枚举所需的命名空间,那么用枚举替换第2点中的宏将看起来很难看。想象一下c.components[Image::Channels::Red]

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-15 10:44:33

标准给出了关于问题1的答案:

9.2/15:分配具有相同访问控制的类的非静态数据成员,以便以后的成员在类对象中具有更高的地址。具有双ff访问控制的非静态数据成员的分配顺序是fi编辑的。实现对齐需求可能导致两个相邻的成员不能在彼此之后立即分配;也可能需要管理虚拟函数和虚拟基类的空间。

问题2的答案有很多种选择。如果您喜欢数组表示法:

  • 为什么不使用switch()来安全地返回对正确元素的引用。
  • 或者更好的是,为什么不用一个真正的数组来代替您的成员呢?

第一个看起来应该是:

代码语言:javascript
复制
struct rgba2
{
    uint8_t r, g, b, a;
    constexpr uint8_t& operator[](size_t x)
    {
        assert(x>=0 && x<4);
        switch (x){
            case 0: return r; 
            case 1: return g;  
            case 2: return b;  
            case 3: return a; 
            //default: throw(1);  // not possible with constexpr
        }
    }
};

第二项是:

代码语言:javascript
复制
struct rgba3
{
    enum ergb { red, green, blue, alpha};
    uint8_t c[alpha+1];
    constexpr uint8_t& operator[](ergb x)
    {
        assert(x>=0 && x<4);
        return c[x];
    }
};

现场演示

票数 2
EN

Stack Overflow用户

发布于 2015-08-15 11:37:01

您可以通过使用指向成员的指针的静态数组,以符合标准的方式高效地完成这一任务。

内存开销是每个类一个数组。在优化的构建中,当索引在编译时已知时,生成的代码与直接成员访问相同。

下面是一些示例代码(来源):

代码语言:javascript
复制
#include <iostream>

template<class T>
class Vector3
{
public:
   Vector3(const T &xx, const T &yy, const T &zz) :
      x(xx), y(yy), z(zz)
   {
   };

   T& operator[](size_t idx)
   {
      return this->*offsets_[idx];
   };

   const T& operator[](size_t idx) const
   {
      return this->*offsets_[idx];
   };

public:
   T x,y,z;
private:
   static T Vector3::* const offsets_[3];
};

template<class T>
T Vector3<T>::* const Vector3<T>::offsets_[3] =
{
   &Vector3<T>::x,
   &Vector3<T>::y,
   &Vector3<T>::z
};

int main()
{
   Vector3<float> vec(1,2,3);
   vec[0] = 5;
   std::cout << vec.x << std::endl;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32023374

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档