使用Lambda表达式mutable有感
在学Qt的时候,我看着mutable陷入了沉思,总觉得它和C++中的某个特性很像?没错,就是 深拷贝
如果你忘记了深拷贝和浅拷贝是什么,那跟着我来一起回忆一下吧。首先来看深拷贝与浅拷贝的概念
浅拷贝
浅拷贝是指在复制对象时,只复制对象本身,而不复制对象所引用的内容。这意味着,当原始对象或复制对象的引用内容发生变化时,另一个对象也会受到影响
深拷贝
深拷贝是指在复制对象时,不仅复制对象本身,还复制对象所引用的内容。这样,当原始对象或复制对象的引用内容发生变化时,另一个对象不会受到影响。
这与浅拷贝不同,浅拷贝只复制对象本身,而不复制对象所引用的内容
以下是一个简单的深拷贝与浅拷贝的示例:
#include <iostream>
using namespace std;
int main() {
int a = 10;
int b = a; // 深拷贝
int *p1 = new int(20);
int *p2 = p1; // 浅拷贝
cout << a << endl; // 输出 10
cout << b << endl; // 输出 10
a = 30;
cout << a << endl; // 输出 30
cout << b << endl; // 输出 10
cout << *p1 << endl; // 输出 20
cout << *p2 << endl; // 输出 20
*p1 = 40;
cout << *p1 << endl; // 输出 40
cout << *p2 << endl; // 输出 40
delete p1;
return 0;
}
在上面的代码中,我们首先定义了两个整数变量a和b,并使用赋值运算符将a的值赋给b。这相当于对b进行了深拷贝,因为它创建了一个新的整数变量,并将a的值复制到了新变量中
细心的同学可能会发现我给出的示例其实是不严谨的,深拷贝和浅拷贝通常用于描述复制对象时的行为(特别是当对象包含指针或引用类型的成员时)。在我给出的简单示例中,我使用了基本类型的变量(即整数变量)来演示深拷贝和浅拷贝的概念。这样做是为了简化示例,让大家更好地理解深拷贝和浅拷贝的区别
Mutable 关键字
默认情况下,Lambda 表达式不能修改以值方式捕获的外部变量。如果您想要在 Lambda 表达式中修改这些变量,那么您需要在参数列表后面添加 mutable
关键字
#include <iostream>
int main()
{
int x = 0;
auto increment = [x]()mutable {
x++;
std::cout << "x in lambda: " << x << std::endl;
};
increment();
increment();
std::cout << "x in main: " << x << std::endl;
return 0;
}
输出的结果为:
x in lambda: 1
x in lambda: 2
x in main: 0
从输出的结果上看,mutable关键字的copy机制和深拷贝非常相像,但我可以很明确的告诉你,mutable的copy机制不属于深拷贝
有同学会疑惑?为什么不属于深拷贝?这个机制不是一模一样的吗?
mutable
关键字确实会为被捕获的变量创建一个副本,并且修改这个副本不会影响外部的变量。但mutable
不是为整个对象创建了一个新的副本。因此,它并不是深拷贝- 深拷贝通常指的是对于一个对象,它的拷贝构造函数或赋值运算符重载函数会创建一个新的对象,并且复制原对象的所有数据,包括指针成员指向的内存
你可以这么理解,捕获和深拷贝都会创建一个副本,但是它们的目的和范围不同。捕获是针对单个变量而言的,它会创建一个被捕获变量的副本。而深拷贝是针对整个对象而言的,它会创建一个新的对象,并复制原对象的所有数据。这两种方式都不会影响被拷贝的变量或对象的值
机制很像,但是在mutable关键字中叫捕获,而不是拷贝
参考资料
1. StackOverFlow | What is the difference between a deep copy and a shallow copy?
2. C++ 中的 mutable 关键字