有效地实施修改操作?

时间:2013-09-20 00:09:29

标签: c++

我想知道,假设我有一些大对象,比如一个矩阵,我想提供一些功能来以某种方式修改这个对象(在矩阵的情况下,我们可能希望反转矩阵)。

实现反转功能的最佳方法是什么?

我想到了四种选择:

  1. 我们可以有一个成员函数,Matrix :: invert()反转自己。
  2. 成员函数可以构造一个新的倒置矩阵(类似于std::string::substr
  3. invert可以是一个非成员函数,它接受并修改引用:void invert(matrix& m)
  4. invert可以是一个非成员函数,它按值获取矩阵,将其反转,然后返回它:matrix invert(matrix m)
  5. 现在,第四个选项对我来说似乎是最好的,因为如果用户希望保留原始矩阵,原件将不会被修改:
    auto m = matrix{};
    auto m2 = invert(m);

    如果他们只想要倒置矩阵,他们可以这样做:
    auto m = matrix{};
    auto m2 = invert(move(m));

    auto m = invert(matrix{})(这应该是有效的,因为新构造的矩阵将被移动到反转,修改,然后rvo'd或移出到m)

    但这违背了影响类表示的操作应该作为成员函数实现的想法。理想情况下,我想要一种实现成员函数matrix& matrix::invert()的方法,如果在rvalue上调用它,则会修改父矩阵,但是如果在左值上调用它则保持原样并返回一个新矩阵。这是正确的做法吗?它怎么可能实现?

    另一种选择可能是实现修改原始成员的成员,以及根据参数是否为rvalue(在这种情况下它将被移动)或者是左值来实现“做正确的事”的非成员(在这种情况下,将制作一份副本)。这仍然有两个缺点:

    1. 更多代码,因为现在我们有两个反转函数
    2. 链接很尴尬,因为我们可能想说m.invert()但不想修改原始矩阵。
    3. 示例:https://gist.github.com/mfaizan/6631482

      谢谢!

3 个答案:

答案 0 :(得分:1)

很容易想象出需要破坏性和非破坏性版本的功能。例如,链表的破坏性反向可以更有效,因为它不需要复制容器值。毫不奇怪,STL有reverse(破坏性)和reverse_copy(非破坏性),但list也有reverse(破坏性)成员函数。

很容易想象可以基于某些受限制的界面实现的功能,但是通过类内部知识可以大大提高其效率。例如,矩阵是否稀疏。我认为在这种情况下,有一个通用接口将参数类型分派给辅助函数是正常的。

答案 1 :(得分:1)

这一切当然都取决于它,但是同时拥有导致新对象的变异动作和动作通常很有用。防爆。你的m.invert()方法可以修改矩阵。它可能比创建新矩阵更有效(它可以在不必分配内存的情况下更改现有值)。但是,有一种方法可以创建与orig断开连接的新对象。

你在std :: string上看到这种模式:

string orig("abcd");
orig += "efgh";

这会改变orig字符串,并且可能会避免内存realloc。 但是,您也可以创建一个全新的字符串:

string newStr = orig + anotherStr;

答案 2 :(得分:1)

您可能还需要考虑另一种可能性:

bool invert (Matrix &);

可以确定矩阵是单数的,在这种情况下返回false并保持矩阵不变。您需要某种方式来报告此案例。

对于小矩阵,缩放(部分)旋转或大型矩阵的更有效方法,无论是使用Cramer规则等,总是存在精度限制。也就是说,结果将受到基质调节的影响。关键是 - 即使矩阵在数学上是可逆的 - 浮点运算也不会产生逆。

“表达式”的多功能表单可能是:Matrix invert (const Matrix &); - 前提是你有移动构造函数/赋值运算符。也许有一个Matrix::Singular异常类。

相关问题