【问题标题】:Create unique pointer inside a function在函数内创建唯一指针
【发布时间】:2020-07-02 15:44:03
【问题描述】:

是否可以在类中声明一个 unique_ptr (nullptr),然后将其原始值 (使用 get()) 传递给创建它将指向的实例的函数?

我必须使用 Qt 制作的界面运行应用程序。 Qt 需要 Qapplication 在更新 UI 的同一线程中启动。为此,由于我也使用 QP 框架(它具有类似于 qt exec() 的阻塞功能),因此我无法在 main 中执行此操作,因此我创建了一个包含 2 个 unique_ptr 的类:

//MyClass.h
std::unique_ptr<Qapplication> Core;
std::unique_ptr<MainWindow> UI;

然后在 MyClass 的构造函数中的代码中启动线程:

std::thread(&MyClass::threadfunc,this, UI.get(), Core.get());

主题是:

int MyClass::threadfunc(MainWindow* UI,Qapplication* Core){
   int dummy=0;
   Core = new QApplication(dummy,nullptr);
   UI= new MainWindows();
   UI->show;
   return Core ->exec();
}

我需要 MyClass 中的指针,因为我需要更新 UI,所以使用指向 mainwindows 的指针我应该能够调用它的方法,但是由于它必须在 QApplication 之后创建,所以我不能在我的类构造函数中引用它. 然后我决定在分离的线程中创建所有,因为我可以保证在 Qt 停止后我的类中的指针将被销毁,我读到可以将指针声明为唯一的(我可以只使用共享指针,但我想了解是否可以使用唯一指针)。 要创建唯一的指针,我需要 make_unique 函数,但由于我传递了原始指针,所以我不能使用它。我什至不能传递指针,因为它们必须是唯一的(我在 MyClass 中使用它们)

问题是,有没有更好的解决方案来实现我想要获得的东西?或者我可以通过我正在使用的实现来获得它吗?

谢谢

【问题讨论】:

  • 当你作为参数传入threadfunc时,为什么要在它们中创建新对象?
  • Core = new QApplication(dummy,nullptr); 在线程内!你在做什么?这段代码证明你是一个初学者,所以在你获得一些经验之前最好不要使用任何类型的线程。
  • 您似乎还使用了线程中的 GUI 元素,而不是 main 正在执行的线程——这是不受支持的。
  • @PaulSanders 因为指针已声明但未指向任何内容。问题是如果我共享指针,是否可以在另一个线程中实例化对象
  • 您的代码没有共享任何内容。我不知道你想做什么。

标签: c++ qt unique-ptr


【解决方案1】:

你的代码太乱了,无法修复。

看起来您正在使用 Qt,所以只有正确使用 QApplication 看起来像这样:

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    MainWindow window;
    window.show();

    return app.exec();
}

你没有必要或技能用它做任何其他事情。 当应用程序没有 UI 模式时,此模式的唯一例外在 documentation 中进行了描述。

不要使用线程。我知道它们现在很流行,这是一个流行词,但它们很难掌握(多线程错误极难修复和理解,而且很容易编写可以在 90% 的计算机上运行并且总是失败的代码在 10% 的机器上),因此初学者应尽可能避免使用此功能。

在没有任何类型的线程的情况下开发 Qt 应用程序的第一个掌握基础知识。

【讨论】:

  • 我不能这样做,因为我的主程序还有一点是阻塞(因为我使用了另一个框架)。但是由于我必须将 QT 用于图形界面,而且它也阻塞了,所以我需要在另一个与我的对象通信的线程中运行它以更新 UI。我读到它必须在主线程中完成,但我也读到它可以在另一个线程中运行它应该可以正常工作
  • 然后编辑您的问题添加有关这两个框架的信息,因为您的问题陈述不正确。这是xy problem 的经典示例。
  • 我指定了-“它需要 Qapplication 在更新 UI 的同一线程中启动。要这样做,** 因为我不能在我的 main 中这样做**,”- 只是因为我的问题不是关于如何运行 qt 应用程序,而是如何以正确的方式传递指针。 qt 部分是为了提供一些上下文,以防有人已经在第二个线程中遇到了运行 qt 的问题并认识到了这种情况。这个问题可能不清楚,因为它导致了这些问题,我会尝试编辑它
【解决方案2】:

是否可以在类中声明一个 unique_ptr (nullptr),然后将其原始值(使用 get())传递给创建它将指向的实例的函数?

你可以,但是你处理这个的方式(从你发布的有限代码中)听起来很复杂。为什么threadfunc 需要接收原始指针?它不能接受唯一的指针吗?好像可以,因为你控制MyClass

无论如何,也许这样的事情会完成你想要的。我们基本上是将threadfunc 中的原始指针填充到类的唯一指针中。

#include <iostream>
#include <memory>
#include <thread>
#include <chrono>
struct A {
  std::unique_ptr<int> p;
  std::thread t1;
  A() {
    p = nullptr; //happens by default, but explicit for OP
    
  }

  void start()
  {
    //int *rawp_;
    t1 = std::thread(&A::threadfunc, this, p.get());
    //p = std::unique_ptr<int>{rawp_};
  }

  void threadfunc(int* rawp){
    rawp = new int(5);
    p = std::unique_ptr<int>{rawp};
    std::cout << "A::p " << *(p) << std::endl;
    std::cout << "Sleeping for 5 seconds" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(1000 * (*rawp)));
  }

  void end()
  {
    t1.join();
  }


};


int main()
{
  A a;
  // std::cout << *(a.p) << std::endl; //--> SEGFAULT
  a.start();      
  a.end();
}

【讨论】:

  • 嗯,这有点像我在想的,但我认为我不能像那样在线程中使用 p。我没有将它作为唯一 ptr 传递的一点是因为我必须将它移动到 func 并因此失去所有权(不能按值传递,我读到是不好的做法传递它的引用)。但我需要在课堂上触发一些事件。我显然是新手,因为它是我的第一个图形应用程序,但您似乎是唯一一个试图理解问题并根据我提供给您的信息尽可能回答问题的人,所以谢谢
  • 啊,好的。在这种情况下,请考虑使用std::shared_ptr,因为它似乎适合您的用例——即,您想要引用计数 + 跨类边界拥有多个所有者。还要查看移动语义 (std::move) 以移动所有权,尽管这可能无法满足您的特定目的。顺便说一句,如果您觉得答案有帮助,请点赞 + 接受!
猜你喜欢
  • 2015-02-02
  • 2011-02-21
  • 2021-07-02
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
相关资源
最近更新 更多