2012-03-23 2 views
4

Пробовал понимать общий указатель на несколько дней, и кажется, что я не могу его получить. Не уверен, что это просто очевидно, или если это слишком сложно. Прежде всего, может ли кто-нибудь, пожалуйста, привести мне пример, в котором вы бы НАСТОЯТЕЛЬНЫ использовали общие указатели. Примеры в Википедии не имеют для меня никакого смысла. И как бы вы передали общий указатель на другую функцию или создали объект с общим указателем. Итак, как вы проходите его и где вы его используете? Любая информация или примеры были бы замечательными.QSharedPointer, как передать их, и они мне нужны?

Кроме того, у меня есть эта проблема, когда я не знаю, что использовать. У меня есть эта функция, где я выделяю QFile и передаю ее функции в другой класс. Эта функция принимает файл как QIODevice*, а затем создает объект, содержащий файл. Мне было интересно, какое лучшее решение будет здесь и как (если я должен) использовать общий указатель здесь? Как я могу сделать общий указатель с <QFile> и передать его там, где функция принимает <QIODevice>. Похоже, что я не получаю общих указателей вообще ...

Мой другой подход состоял бы в том, чтобы разместить выделение QFile в QScopedPointer. Затем я передаю его классу и при создании объекта, в котором будет сохранен файл, я использую QPointer или QScopedPointer. В конце первой функции вызова я должен позвонить take() правильно?

function() { 
    QScopedPointer<QFile> item(new QFile("filename")); 
    SomeClassObject->doStuff(item.data()); 
    item.take(); 
} 
--------------------------------- 
SomeClass::doStuff(QIODevice *item) { 
    _currentObject = new MyObject(item); // should _currentObject be a smartpointer? 
    ... 
} 
--------------------------------- 
class MyObject { 
    QPointer<QIODevice> _item; 

    ... 
    MyObject(QIODevice *item) { _item = item; } 
} 

Поэтому я хочу способ хранения указателей и способ их обработки в процессе создания, если «новый» бросает исключение.

ответ

8

Точка общих указателей (и других подобных оберток для указателей) предназначена для правильной обработки указателя-объекта. Это вместо того, чтобы вручную убедиться, что вы удаляете последнюю копию (и только последнюю копию), общий указатель позаботится об этом для вас, когда он выходит за рамки. Совместная часть означает, что вы можете создавать копии этого объекта-обертки (общий объект-указатель), и он будет «разделять» указатель на объект между копиями (как если бы вы сделали копию обычного указателя) с добавленной выгодой описано выше.

Что касается вашего кода, SomeClass::doStuff() должен иметь QScopedPointer<QFile> параметр (вместо QIODevice* один), как вы передаете item к нему, которое имеет этот тип.

То же самое с конструктором MyObject: имеет значение QPointer<QIODevice> или QSharedPointer<QIODevice>. В общем, везде, где вы использовали указатели, вместо этого используйте QSharedPointer (с соответствующим типом шаблона). Это избавит вас от головных болей, связанных с доступом к удаленным объектам позже.

Конечно, иногда вам нужен необработанный указатель QIODevice (например, для вызова сторонней библиотеки), тогда вы должны использовать функцию-член data() объекта общего указателя. Просто убедитесь, что вы не сохраняете (то есть хранилище или иным образом копируете за пределы необходимого) возвращенный необработанный указатель, потому что это приведет к подрыву цели общих указателей - общие указатели не будут знать о вашем дополнительном необработанном указателе, который не находится под управление общими объектами указателя.

EDIT: take() освобождает право собственности на объект с указателем на объект с помощью указателя на область действия, поэтому, когда указатель области действия уничтожен, он не удаляет объект. Вы могли бы использовать его в ситуации, когда вы передавали право собственности на что-то еще - например, в вашем случае - MyObject.

+1

Я не вижу веской причины сделать аргумент функции 'QScopedPointer'.Либо сделайте это * ссылкой * (вообще избегайте указателей), оставьте его как необработанный указатель (разрешите * все * управляемые типы указателей) или сделайте его общим указателем (не копируйте и не делайте '_currentObject' обмениваться объектом, если это возможность). Передача указателя с областью должна быть по ссылке, а затем вы вынуждаете выбор умного указателя на своих пользователей, что не очень приятно делать (что, если они используют другой тип смарт-указателя?) –

+1

Я не вижу почему передача общего указателя (вместо исходного) является проблемой (помимо форсирования конкретного типа). Я думаю, что это безопаснее, чем передача необработанного указателя (например, вы можете сохранить этот параметр в глобальном контейнере, не опасаясь, что вызывающий его удалит из-под вас). Общий указатель, безусловно, не должен быть по ссылке, логика-конструктор-копир будет следить за тем, чтобы копия соответствовала. Вы могли бы передать базовый объект через ссылку, но зачем вообще использовать указатели? – Attila

+0

ему нужно взять QIODevice, так как я буду использовать его не только с QFile. В моем коде есть другие ситуации, где функции должны принимать basetype – chikuba