代码之家  ›  专栏  ›  技术社区  ›  Ozgur Ozcitak Vikash Choudhary

如何防止在级联运算符中创建中间对象?

  •  2
  • Ozgur Ozcitak Vikash Choudhary  · 技术社区  · 18 年前

    我在应用程序中使用自定义矩阵类,并且经常添加多个矩阵:

    Matrix result = a + b + c + d; // a, b, c and d are also Matrices
    

    但是,这会为每个加法操作创建一个中间矩阵。由于这是简单的加法,因此可以避免中间对象,并通过一次添加所有4个矩阵的元素来创建结果。我怎样才能做到这一点?

    Add3Matrices(a, b, c) , Add4Matrices(a, b, c, d) 等,但我想保持 result = a + b + c + d .

    11 回复  |  直到 18 年前
        1
  •  8
  •   Ian G    18 年前

    通过使用惰性评估,您可以将自己限制为一个小的中间层。差不多

    public class LazyMatrix
    {
        public static implicit operator Matrix(LazyMatrix l)
        {
            Matrix m = new Matrix();
            foreach (Matrix x in l.Pending)
            {
                for (int i = 0; i < 2; ++i)
                    for (int j = 0; j < 2; ++j)
                        m.Contents[i, j] += x.Contents[i, j];
            }
    
            return m;
        }
    
        public List<Matrix> Pending = new List<Matrix>();
    }
    
    public class Matrix
    {
        public int[,] Contents = { { 0, 0 }, { 0, 0 } };
    
        public static LazyMatrix operator+(Matrix a, Matrix b)
        {
            LazyMatrix l = new LazyMatrix();
            l.Pending.Add(a);
            l.Pending.Add(b);
            return l;
        }
    
        public static LazyMatrix operator+(Matrix a, LazyMatrix b)
        {
            b.Pending.Add(a);
            return b;
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Matrix a = new Matrix();
            Matrix b = new Matrix();
            Matrix c = new Matrix();
            Matrix d = new Matrix();
    
            a.Contents[0, 0] = 1;
            b.Contents[1, 0] = 4;
            c.Contents[0, 1] = 9;
            d.Contents[1, 1] = 16;
    
            Matrix m = a + b + c + d;
    
            for (int i = 0; i < 2; ++i)
            {
                for (int j = 0; j < 2; ++j)
                {
                    System.Console.Write(m.Contents[i, j]);
                    System.Console.Write("  ");
                }
                System.Console.WriteLine();
            }
    
            System.Console.ReadLine();
        }
    }
    
        2
  •  3
  •   Vinko Vrsalovic    18 年前

    至少可以避免痛苦的事情

    Matrix Add3Matrices(a,b,c) //and so on 
    

    Matrix AddMatrices(Matrix[] matrices)
    
        3
  •  3
  •   David Dibben    18 年前

    在C++中,可以使用 Template Metaprograms 而且 here ,使用模板来完成此操作。然而,模板编程是非常重要的。我不知道C语言中是否有类似的技术,很可能没有。

    C++中的这个技术正好符合你的需要。缺点是,如果某些地方不太正确,那么编译器错误消息往往会运行到多个页面,并且几乎无法破译。

    如果没有这样的技术,我怀疑您仅限于add3矩阵之类的函数。

    Efficient Matrix Programming in C# 虽然它看起来与C++模板表达式略有不同。

        4
  •  3
  •   workmad3    18 年前

    但是,您可以使用如上所述的表达式模板 here 将它们最小化,并对模板进行评估。

        5
  •  2
  •   Tetha    18 年前

    这不是最干净的解决方案,但如果您知道评估顺序,可以执行以下操作:

    result = MatrixAdditionCollector() << a + b + c + d
    


    我不完全确定这是丑陋的地狱或一个更好的黑客之一可能会做。一个明显的优势是,这是正在发生的事情。

        6
  •  2
  •   Orion Adrian    18 年前

    我建议使用一种行为非常像StringBuilder的MatrixAdder。将矩阵添加到MatrixAdder中,然后调用ToMatrix()方法,该方法将在惰性实现中为您添加矩阵。这将得到您想要的结果,可以扩展到任何类型的懒散评估,但也不会引入任何可能会混淆其他代码维护者的聪明实现。

        7
  •  2
  •   Emil Rasmussen    18 年前

    我认为您可以将所需的插件行为明确化:

    Matrix result = a;
    result += b;
    result += c;
    result += d;
    

    Matrix result = a;
    result = result + b;
    result = result + c;
    result = result + d;
    

    因此,临时机构仍然存在。

        8
  •  1
  •   gnobal    18 年前

    比亚恩·斯特劳斯特鲁普有一篇短文,叫做 Abstraction, libraries, and efficiency in C++ Blitz++ ,一个用于科学计算的库,它还具有矩阵的高效运算,以及一些其他有趣的库。另外,我建议你阅读 a conversation with Bjarne Stroustrup on artima.com 关于这个问题。

        9
  •  0
  •   Romain Verdier    18 年前

    使用运算符是不可能的。

        10
  •  0
  •   Kokuma    18 年前

    static Matrix AddMatrices(Matrix[] lMatrices) // or List<Matrix> lMatrices
    {
        // Check consistency of matrices
    
        Matrix m = new Matrix(n, p);
    
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                foreach (Maxtrix mat in lMatrices)
                    m[i, j] += mat[i, j];
    
        return m;
    }
    

    当然,你会失去 result = a + b + c + d . 但是你会有一些类似于 result = Matrix.AddMatrices(new Matrix[] { a, b, c, d }); .

        11
  •  0
  •   OldMan    18 年前

    有几种方法可以实现惰性评估来实现这一点。但重要的是要记住,编译器并不总是能够获得所有代码中最好的代码。

    推荐文章