C++ lazy evaluation(延迟计算或惰性求值)介绍

x33g5p2x  于2022-07-19 转载在 其他  
字(2.5k)|赞(0)|评价(0)|浏览(216)

**      C++****中的lazy evaluation or call-by-need(****延迟计算或按需调用)**是一种求值策略,其中表达式在第一次使用之前不求值,即将求值推迟到真正需要时

**     **为一个最终可能不需要的计算付出性能代价显然不是明智之举。然而在复杂的代码中这种情况比比皆是。我们不应该执行"只在某种情况下"才需要的昂贵计算,而应该只在必要的时候执行昂贵计算。这通常意味着把计算推迟到真正需要的时候才进行,因此称之为延迟计算或惰性求值。在C++中,对象的定义会调用构造函数和析构函数,这可能是高成本的,因为它导致了立即计算----而这正是我们所要避免的。延迟计算原则建议我们推迟对象的定义,直到要使用该对象时再定义。为不一定用到的构造函数和析构函数付出代价是没有意义的。不仅应该将对象的创建推迟至合适的位置,而且应该直到具备了一个有效创建操作所必需的全部条件后,再创建对象。

**     **当你使用了lazy evaluation后,采用此种方法的类将推迟计算工作直到系统需要这些计算的结果。如果不需要结果,将不用进行计算。

**     **在某些情况下要求软件进行原来可以避免的计算,这时lazy evaluation才是有用的。

**     **下面是两个采用lazy evaluation的测试代码段:

    1.通过引用计数减少不必要的拷贝:

int test_evaluation_1()
{
    // 引用计数: 除非你确实需要,否则不去为任何东西制作拷贝.我们应该是lazy的,只要有可能就共享使用其它值
    std::string str1 = "hello";
    std::string str2 = str1; // str2和str1指向同一块内存地址
    fprintf(stdout, "pointer: str1: %p, str2: %p\n", // pointer: str1: 0x2061208, str2: 0x2061208
        static_cast<void*>(const_cast<char*>(str1.c_str())), static_cast<void*>(const_cast<char*>(str2.c_str())));

    str2 = "beijing"; // str2被重新赋值后,str2和str1不在指向同一块内存地址
    fprintf(stdout, "pointer: str1: %p, str2: %p\n", // pointer: str1: 0x2061208, str2: 0x2061648
        static_cast<void*>(const_cast<char*>(str1.c_str())), static_cast<void*>(const_cast<char*>(str2.c_str())));

    return 0;
}

**     **2.矩阵运算中,在真正使用时才做运算,通过运算符重载实现:

using matrix = std::array<int, 2>;

// write this proxy
struct matrix_add {
    matrix_add(const matrix& a, const matrix& b) : a_(a), b_(b) { fprintf(stdout, "do nothing\n"); }

    // an implicit conversion operator from matrix_add to plain matrix
    // the evaluation takes place only when the final result is assigned to a matrix instance
    operator matrix() const {
        fprintf(stdout, "add operation\n");
        matrix result;
        for (int i = 0; i < 2; ++i)
            result[i] = a_[i] + b_[i];

        return result;
    }

    // calculate one element out of a matrix sum
    // it's of course wasteful to add the whole matrices
    int operator ()(unsigned int index) const {
        fprintf(stdout, "calculate *just one* element\n");
        return a_[index] + b_[index];
    }

private:
    const matrix& a_, b_;
};

// to make this function lazy, it's enough to return a proxy instead of the actual result
matrix_add operator + (const matrix& a, const matrix& b)
{
    return matrix_add(a, b);
}

int test_evaluation_2()
{
    // reference: https://stackoverflow.com/questions/414243/lazy-evaluation-in-c
    // 矩阵计算: 主要机制是运算符重载
    matrix mat1 = {2, 3}, mat2 = {7, 8};
    auto ret = mat1 + mat2;
    fprintf(stdout, "... ...\n");
    matrix mat3(ret); // implicit conversion from matrix_add to matrix

    fprintf(stdout, "one element sum: %d\n", ret(1));

    return 0;
}

    执行结果如下图所示:

    GitHub: https://github.com/fengbingchun/Messy_Test

相关文章

微信公众号

最新文章

更多