Не имеет смысла передавать слабый указатель, так как единственный способ безопасного использования слабого указателя - вернуть его в общий указатель. В этом отношении api несколько искажен, так как позволяет использовать QWeakPointer::data()
для обмана - но это глупо, вы никогда не должны использовать его таким образом. std::weak_ptr
получил это право, и вы не можете использовать его, кроме как лить его на std::shared_ptr
.
Но все равно это не обязательно.
Контейнеры Qt являются неявно разделяемыми классами значений. Передача их указателями излишняя. A 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, но этот стиль является преждевременным pessimization в 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
- это QScopedPointer
к его pimpl, как и большинство других классов 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));
}
Лучшая практика QTSmartPointers, чтобы никогда не использовать QTSmartPointers :) – SergeyA
[Это] (http://stackoverflow.com/questions/12030650/when-is-stdweak-ptr-useful) и [это] (http://stackoverflow.com/questions/8385457/should-i-pass-a-shared-ptr-by-reference) в значительной степени суммирует его. Они о стандартной библиотеке, но в чем разница? – LogicStuff