gpt4 book ai didi

c++ - 函数参数中的Qt智能指针

转载 作者:行者123 更新时间:2023-11-28 00:02:25 34 4
gpt4 key购买 nike

我正在寻找 Qt 智能指针的最佳实践。假设我有这样的东西。

void aFunction() {
QSharedPointer<QVector<QSharedPointer<Object> > > pointer = QSharedPointer<QVector<QSharedPointer<Object> > >(new QVector<QSharedPointer<Object> >);

doSomethingWithPointer(pointer);
changeOwnership(pointer);
}

然后在doSomethingWithPointer函数中

void doSomethingWithPointer(QSharedPointer<QVector<QSharedPointer<Object> > > pointer) {
pointer->append(QSharedPointer<Object>(new Object);
}

现在我在 doSomethingWithPointer 之后,将指针传递给 changeOwnership,它应该拥有它的所有权。我想知道的是 doSomethingWithPointer。在这样的函数中传递共享指针可以吗?或者我应该使用 QWeakPointer 因为 doSomethingWithPointer 实际上并不拥有指针的所有权?我究竟应该在什么时候使用 QWeakPointer?

最佳答案

传递弱指针没有多大意义,因为安全使用弱指针的唯一方法是将其转换回共享指针。 Qt 的 api 在这方面有些问题,因为它允许您使用 QWeakPointer::data() 作弊 - 但那很愚蠢,您永远不会以这种方式使用它。 std::weak_ptr 正确,除了将其转换为 std::shared_ptr 之外,您无法使用它。

但这一切都不是必需的。

Qt 的容器是隐式共享值类。通过指针传递它们是多余的。 QVector 在内部是指向其数据的共享指针。当您想要放弃其所有权时,您可以利用移动语义来消除否则会发生的隐式共享。

在您的特定情况下,答案是:根本不要使用外部共享指针。

struct Object {};

void appendObject(QVector<QSharedPointer<Object>> & data) {
data.append(QSharedPointer<Object>(new Object));
}

void use(QVector<QSharedPointer<Object>> && data) {
}

int main() {
QVector<QSharedPointer<Object>> data;
appendObject(data);
use(std::move(data));
}

边栏:在 C++11 中,您会期望 uniform initialization工作 - 但它不会因为 QVector 和/或 QSharedPointer 有不兼容的 API。所以这很好,但没有骰子:

data.append({new Object});

以 Qt 4 风格编写并依赖于 Qt 容器的隐式共享是可以接受的,但这种风格在 Qt 5/C++11 中是过早的悲观化:

void use(QVector<QSharedPointer<Object>> & data) {
}

int main() {
QVector<QSharedPointer<Object>> data;
appendObject(data);
use(data);
}

同样值得研究的是,Object 是否可以作为值类工作,可以按值直接存储在容器中。

即使不是这种情况,如果您真的不需要 Object 的共享所有权,而只是一个动态分配的容器,您可以改用 QList:

struct Object {};

void appendObject(QList<Object> & data) {
data << Object();
}

void use(QList<Object> && data) {
}

int main() {
QList<Object> data;
appendObject(data);
use(std::move(data));
}

如果对象不可复制,您应该使用 std::list 并利用移动语义来更改所有权:

void appendObject(std::list<QObject> & data) {
data.emplace_back();
}

void use(std::list<QObject> && data) {
}

int main() {
std::list<QObject> data;
appendObject(data);
use(std::move(data));
}

最后,如果您管理的类派生自 QObject,您可以利用 QObject 作为 QObject 容器:

void appendObject(QObject * container) {
new QObject(container); // add a child
}

void use(QScopedPointer<QObject> && container) {
for (auto object : container->children())
qDebug() << object;
}

int main() {
QScopedPointer<QObject> container;
appendObject(container.data());
use(std::move(container));
}

由于 QObject 内部使用 PIMPL,we can too ,从而摆脱愚蠢的外部指针。毕竟,QObject 是其 pimpl 的 QScopedPointer,就像大多数其他 Qt 类一样!

#include <QtCore>
#include <private/qobject_p.h>

class Container : public QObject {
public:
Container(QObject * parent = 0) : QObject(parent) {}
Container(Container && other) :
QObject(*new QObjectPrivate, other.parent()) {
d_ptr.swap(other.d_ptr);
}
};

void appendObject(Container & container) {
new QObject(&container); // add a child
}

void use(Container && container) {
for (auto object : container.children())
qDebug() << object;
}

int main() {
Container container;
appendObject(container);
appendObject(container);
use(std::move(container));
}

最后,如果您希望容器“小”,即元素数量 * 元素大小小于 1-4kbytes,则不要使用 std::listQList,但分别是 std::vectorQVector。一般来说,在任何具有多级内存缓存的现代架构上,小列表的性能都非常差。对于没有内存缓存的简单微 Controller 来说,它们可能没问题,所以我们在这里讨论的是 Arduino 性能水平,但即便如此,也必须先进行测量。

关于c++ - 函数参数中的Qt智能指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37813706/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com