将点传递给线程并对其进行修改

Posted

技术标签:

【中文标题】将点传递给线程并对其进行修改【英文标题】:Pass a point into a thread and have it modified 【发布时间】:2018-04-16 20:52:32 【问题描述】:

我需要保留传递给线程的对象的引用。设置环境的方式我必须将应用程序特定的绘图保留在它启动的同一线程中。因此,我将应用程序初始化代码隐藏在一个线程中,然后获取对我感兴趣的自定义组件的引用。

这行不通。应用程序加载并显示正常,但主线程中指向应用程序的指针始终为null。即使我使用std::shared_ptrstd::ref。我做什么似乎无关紧要,指针始终为空。

#include <thread>
#include <iostream>

class SomeClass 
public: 
   int value;

    SomeClass()  value = 0; 
;

void ExecuteThread(SomeClass* c) 
  c = new SomeClass();
  c->value = 555;


int main(int argc, char** argv) 
SomeClass* c = nullptr;

// std::ref(c) doesn't work 
// Have also tried passing std::shared_ptr<SomeClass> 
std::thread t1 = std::thread(&ExecuteThread, c);

t1.join();

std::cout << "c: " << c << "\n";
std::cout << "c->value: " << c->value << "\n";

return 0;

【问题讨论】:

你误解了复制指针的作用。您有两个 Canvas 指针,您只更改其中一个。 @RinatVeliakhmedov 我确实提到了为什么我需要这样做。 @DrewDormann 它是一个指针而不是一个值。即使我在指针周围使用std::ref,问题也是一样的。 你能在没有 Qt 的情况下重现这个问题吗? @Maverick 在您显示的代码中,您有两个不同的指针。改变一个不会改变另一个。 (您的问题与 Qt 无关,而是与指针的工作原理有关。)我无法使用 std::ref 评论您代码中的错误,因为我看不到它。 @SergeyA 我使用具有一个成员变量的类为该问题编写了一个测试平台。同样的问题。所以它与QT无关。无论我尝试做什么以将引用传递给新线程,似乎 std::thread 都会复制。这是令人难以置信的误导,因为我在网上花了几个小时寻找在线传递指针和共享指针的方法,这就是他们所说的线程。 【参考方案1】:

为了避免人们对错误的自我回答感到困惑,我提供了我自己的正确答案。

OPs 代码的主要问题是按值传递指针会复制指针,对它的任何修改都不会影响原始指针。线程不会改变这个事实,也不会增加任何东西。特别是代码可以表示为

 void change(int* k) 
      k = nullptr;
 

 int i;
 k = &i;
 change(k);
 // k here is still the same as before calling `change`

如果要更改传递的指针,则应将其作为引用传递:void change(int*&amp; k)

这里有线程会稍微改变一些事情。由于无法通过引用将某些内容传递给std::thread 构造函数,因此需要使用std::ref。函数签名仍应通过引用接受指针,并且应在创建线程的地方使用std::ref

auto t = std::thread(change, std::ref(k))

【讨论】:

【参考方案2】:

std::thread 秘密复制您作为参数传递的所有内容包括指针数据。这是令人难以置信的误导。解决这个问题的唯一方法是将地址传递给指针并让线程复制那个。然后在你线程的任务中,尊重一个指针。

#include <thread>
#include <iostream>

class SomeClass 
public: 
   int value;

    SomeClass()  value = 0; 
;

void ExecuteThread(SomeClass** c) 
  *c = new SomeClass();
  *c->value = 555;


int main(int argc, char** argv) 
SomeClass* c = nullptr;

std::thread t1 = std::thread(&ExecuteThread, &c);

t1.join();

std::cout << "c: " << c << "\n";
std::cout << "c->value: " << c->value << "\n";

return 0;

【讨论】:

不,任何地方都没有秘密副本。您的原始代码按值接受指针,因此对它的任何修改都将丢失。没有线程也不例外。 @Maverick 在说什么?按值传递指针总是复制指针 当两个代表大约 30K 的人告诉一个代表 82 的人这个人错了,这个人重新考虑通常是明智的。不过,你可以适合自己。 致版主标记此答案的人:不要仅仅因为您认为答案错误而标记答案。版主不参与此类争议。跨度> @Maverick 该代码 sn-p 调用 undefined behavior 因为您取消引用空指针(在 IDEOne 上它会导致“运行时错误”:ideone.com/Gu0x2F)跨度>

以上是关于将点传递给线程并对其进行修改的主要内容,如果未能解决你的问题,请参考以下文章

怎样将数据库中数据表显示在MFC中的列表控件上,并对其进行删除,修改

ExtJS - 依赖组合框

通过参数传递变量并稍后在类中对其进行修改

Xmpp 消息边界

可变关键字线程安全[重复]

Angular2:通过引用传递组件之间的交互