问题描述
我是新的线程在C + +,我试图得到一个清晰的图片,如何共享/不共享线程之间的内存。我使用 std :: thread
和C ++ 11。
根据我在其他SO问题上阅读的内容,堆栈内存仅由一个线程拥有,堆内存在线程之间共享。所以从我认为我理解堆栈与堆,以下应该是真的:
I'm new to threading in C++, and I'm trying to get a clear picture about how memory is shared/not shared between threads. I'm using std::thread
with C++11.From what I've read on other SO questions, stack memory is owned by only one thread and heap memory is shared between threads. So from what I think I understand about the stack vs. the heap, the following should be true:
#include <thread>
using namespace std;
class Obj {
public:
int x;
Obj(){x = 0;}
};
int main() {
Obj stackObj;
Obj *heapObj = new Obj();
thread t([&]{
stackObj.x++;
heapObj->x++;
});
t.join();
assert(heapObj->x == 1);
assert(stackObj.x == 0);
}
原谅我,如果我搞砸了一堆东西,lambda语法是非常新的对我来说。但希望我想要做的是一致的。
这将如我所料吗?如果不是,我误解了什么?
forgive me if I screwed up a bunch of stuff, lambda syntax is very new to me. But hopefully what I'm trying to do is coherent.Would this perform as I expect? And if not, what am I misunderstanding?
推荐答案
内存是内存。 C ++中的对象占用内存中的一些位置;该位置可以在堆栈上或堆上,或者它可能已被静态分配。无论对象位于何处:具有引用或指向该对象的指针的任何线程都可以访问该对象。如果两个线程有一个引用或指向该对象的指针,那么这两个线程都可以访问它。
Memory is memory. An object in C++ occupies some location in memory; that location may be on a stack or on the heap, or it may have been statically allocated. It doesn't matter where the object is located: any thread that has a reference or pointer to the object may access the object. If two threads have a reference or a pointer to the object, then both threads may access it.
在程序中,创建一个工作线程c $ c> std :: thread ),它执行你提供的lambda表达式。因为你通过引用捕获 stackObj
和 heapObj
(使用 [& code> capture default),那个lambda对这两个对象都有引用。
In your program, you create a worker thread (by constructing a
std::thread
) that executes the lambda expression you provide it. Because you capture both stackObj
and heapObj
by reference (using the [&]
capture default), that lambda has references to both of those objects.
这些对象都位于主线程的栈上(注意
heapObj
是一个指针类型的对象,它位于主线程的堆栈上,并指向一个动态分配的对象,它位于堆上)。没有这些对象的副本;而是,您的lambda表达式具有对对象的引用。它直接修改 stackObj
,并间接修改 heapObj
指向的对象。
Those objects are both located on the main thread's stack (note that
heapObj
is a pointer-type object that is located on the main thread's stack and points to a dynamically allocated object that is located on the heap). No copies of these objects are made; rather, your lambda expression has references to the objects. It modifies the stackObj
directly and modifies the object pointed to by heapObj
indirectly.
主线程加入工作线程后,
heapObj-> x
和 stackObj.x
有 1
的值。
After the main thread joins with the worker thread, both
heapObj->x
and stackObj.x
have a value of 1
.
使用值捕获默认值(
[=]
),您的lambda表达式将 复制 stackObj
和 heapObj
。在lambda表达式中的表达式 stackObj.x ++
会增加 copy ,而 stackObj
您在 main()
中声明的名称将保持不变。
If you had used the value capture default (
[=]
), your lambda expression would have copied both stackObj
and heapObj
. The expression stackObj.x++
in the lambda expression would increment the copy, and the stackObj
that you declare in main()
would be left unchanged.
如果您通过值捕获
heapObj
,则只复制指针本身, ,它仍然指向同一个动态分配的对象。表达式 heapObj-> x ++
将取消引用该指针,产生通过创建的
,并增加其值。然后,您会在 Obj
new Obj() main()
结束时观察到 heapObj-> x
已递增。
If you capture the
heapObj
by value, only the pointer itself is copied, so while a copy of the pointer is used, it still points to the same dynamically allocated object. The expression heapObj->x++
would dereference that pointer, yielding the Obj
you created via new Obj()
, and increment its value. You would then observe at the end of main()
that heapObj->x
has been incremented.
(注意,为了修改通过value捕获的对象,lambda表达式必须声明为
mutable
。)
(Note that in order to modify an object captured by value, the lambda expression must be declared
mutable
.)
这篇关于C ++线程之间的内存共享的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!