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

Posted fengbingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ lazy evaluation(延迟计算或惰性求值)介绍相关的知识,希望对你有一定的参考价值。

      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

以上是关于C++ lazy evaluation(延迟计算或惰性求值)介绍的主要内容,如果未能解决你的问题,请参考以下文章

Rust 内存管理之声明延迟计算的常量 - Rust 实践指南

C# Lazy Loading

Hibernate延迟加载Lazy

Hibernate延迟加载Lazy

Hibernate延迟加载Lazy

C# 延迟处理类 Lazy