【问题标题】:c++ how to define cast operator that doesn't copy data?c ++如何定义不复制数据的强制转换运算符?
【发布时间】:2012-03-29 03:49:09
【问题描述】:

好的 - 也许这是一个愚蠢的问题,演员表操作员已经天生就这样做了..

我有什么:

  • 4x4 矩阵的一些外部类定义

  • 一些自己的 4x4 矩阵类

两个类都简单地存储一个浮点数[16];

我想在我的 Matrix 类中定义一个强制转换运算符,以便我可以执行以下操作:

MyMatrix4x4 m;
OtherMatrix4x4(m).someFunctionDefinedInOtherMatrix4x4();
SomeFunctionThatTakesOtherMatrix4x4(OtherMatrix4x4(m));

而且我不希望该运算符复制任何数据 - 函数应该简单地对相同的 float[16] 数据进行操作

怎么做?

【问题讨论】:

  • 您应该使用指针,但我会让 C++ 专业人士为您提供详细信息。
  • 如果可能,您应该将矩阵实现为派生并覆盖某些功能,而不是在不相关的类型之间进行转换。

标签: c++ casting operators


【解决方案1】:

而且我不希望该运算符复制任何数据 - 函数应该简单地对相同的 float[16] 数据进行操作

我不想在堆上创建任何数据。希望它可以与堆栈上的值一起使用 - 并且为了方便我想要一个演员操作员

这不会发生。 C++ 的别名规则几乎禁止这样做。

您可以使用指针转换来“假装这是别的东西”,但您不能使用对象转换来做到这一点。您可以将指向堆栈对象的指针转换为指向您的对象类型的指针:

MyMatrix4x4 m;
OtherMatrix4x4 * o = (OtherMatrix4x4 *) &m;

但是,有两个问题。首先,o 的持续时间与m 一样长。它不是一个对象;它是指向不同对象的指针。其次,这样做是(通常)未定义的行为(部分原因是违反了别名:两种不相关的类型重叠)。哦,很有可能它会起作用。但就 C++ 所保证的而言,您不在地图范围内。

这有点过早优化的味道。你真的认为复制 16 个浮点数是 很大的性能问题吗?如果是,那为什么不在代码中使用OtherMatrix4x4 而不是MyMatrix4x4

【讨论】:

  • 如果 OtherMatrix4x4 有其他内部成员(助手)怎么办?如果两个类都不是 POD 怎么办?
  • @Andrei:是的。和?我不确定你想在这里做什么。 OP 建议这些类只是float[16]s,上面有一些方法。如果他们不是,那么他想要的只是更多不可能。
  • +1 表示“过早优化的味道”,以及提到的其他内容。
  • 从技术上讲,他只是说“有效载荷”是一个浮点数[16],仅此而已。这将很快变得丑陋,应该尽早停止:)
  • @Andrei:我不反对,这就是为什么我通常会说它行不通,以及为什么我把最后一段放在那里。
【解决方案2】:
OtherMatrix4x4(m)

这不是强制转换运算符,而是转换构造函数

假设MyMatrix4x4的定义如下:

struct MyMatrix4x4
{
    float x[16];
};

以下应该做到这一点:

struct OtherMatrix4x4
{
    float* x;
    OtherMatrix4x4(MyMatrix4x4& other)
    {
       x = other.x;
    }
    void foo()
    {
       x[0] = 0;
    }
};

测试:

MyMatrix4x4 a = {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}};
OtherMatrix4x4(a).foo();
cout << b.x[0]; //will output 0, not 1

编辑这是您无法编辑其他矩阵的版本:

struct OtherMatrix4x4
{
    float x[16];
    void foo()
    {
        x[0] = 0;
    }
};

struct MyMatrix4x4
{
    float* x;
    operator OtherMatrix4x4()
    {
        OtherMatrix4x4 other;
        x = other.x;
        return other;
    }
};

MyMatrix4x4 m;
OtherMatrix4x4(m).foo();

【讨论】:

  • mmmh - 但我无法编辑 OtherMatrix4x4。好的 - (OtherMatrix4x4)(m) 怎么样?
  • 使用这个方法要非常小心,因为这不是一个拥有指针,这可能会让事情变得混乱。
  • @MooingDuck 我知道,这就是我没有编写析构函数的原因。我希望他能理解背后的逻辑。
【解决方案3】:

只是为了提出一个不同的解决方案来呈现继承。这些将允许使用您在上面发布的代码。但是,这不是强制转换运算符。

class MyMatrix4x4 {
public:
    float f;
};

class OtherMatrix4x4 : MyMatrix4x4  {
public:
    OtherMatrix4x4(MyMatrix4x4 &matrix)
    {
        f = matrix.f;
    }

    void someFunctionDefinedInOtherMatrix4x4();
};

【讨论】:

  • 那还在做副本,这是他想要避免的。他真的想要两个引用相同内存的对象。
  • @MooingDuck:您不能将成员添加到现有对象。你不能仅仅因为它是一个派生类就假装MyMatrix4x4OtherMatrix4x4。 C++11 的新标准布局规则可能让您这样做,但 C++03 肯定不会。而且你绝对不能按照他想要的方式去做,那就是让一个对象实例变成一个没有副本的不同对象实例。
  • @NicolBolas:是的,从头到尾都没有这么想。他要么必须制作一个非拥有的 Matrix 类,要么复制一份。
  • 我认为继承在这里不好,因为我正在使用原始 c 结构,并且一旦继承在播放中,就会发生改变大小/内存的虚函数指针的东西结构/类的布局
  • 毕竟我不会关心复制,只要您注意复制那些不会发生在循环内。只需在需要相应对象之前和之后执行一次。这应该是可能的。
猜你喜欢
  • 1970-01-01
  • 2018-03-15
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
  • 2014-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多