含义:将计算拖延到必须计算的时候,以下为4个场景
优点:避免不必要的计算,节省成本
缺点:
- 管理复杂性:可能会增加代码复杂性,特别是在多线程环境中需要正确处理同步和并发问题。
- 性能开销:如果没有正确地实现,可能会导致性能问题,例如,频繁的延迟加载操作可能会导致多次不必要的数据库查询或资源请求
reference counting
- eager evaluation:调用拷贝构造函数,分配内存,并将s1的值拷贝到s2
- lazy evaluation:只有当修改s2的值才进行上述分配内存拷贝的动作
class MyString : public std::string {
public:void convertToUpperCase() {// 具体实现}
};
int main() {MyString s1 = "hello";MyString s2 = s1;std::cout << s1;std::cout << s1 + s2;s2.convertToUpperCase();return 0;
}
区分读和写
和上述场景相似,但是需要在重载operator[]时,区分读和写
int main() {MyString s = "home";std::cout << s[3];s[3] = 'x';return 0;
}
lazy fetching
懒加载:指仅在需要数据时才从加载数据,而不是在建立对象时就加载所有可能需要的数据
class ObjectID {};
class LargeObject {
public:LargeObject(ObjectID id): id(id), field1Value(nullptr)field2Value(nullptr)field3Value(nullptr) {}const std::string field1() const {if (field1Value == nullptr) {// 读取数据库的值}return *field1Value;}int field2() const {if (field2Value == nullptr) {// 读取数据库的值}return *field2Value;}double field3() const {}
private:ObjectID id;mutable std::string *field1Value;mutable int *field2Value;mutable double *field3Value;
};
void restoreAndprocessObject(ObjectID id) {LargeObject object(id);if (object.field2() == 0) {std::cout << "Object " << id << ": null field2.\n";}
}
lazy expression evaluation
策略:设计一个数据结构来记录
- m3:可以用两个指针和一个enum记录,前者指向m1和m2,后者记录一个加法
- 当m3=m4*m1时候,仅仅更改记录,省下了m1+m2的成本
- m3[4]:这种输出只需要计算一部分
-
m1 = m4:当修改了m1的值,不能改变m3的值,因此需要先计算m3的值或者创建m1的副本
template<typename T>
class Matrix {
public:Matrix(int m, int n) {}
};
int main() {Matrix<int> m1(1000, 1000);Matrix<int> m2(1000, 1000);Matrix<int> m3 = m1 + m2;Matrix<int> m4(1000, 1000);m3 = m4 * m1;std::cout << m3[4];m1 = m4;return 0;
}