14

新しいプロジェクトで C++11 スマート ポインターを使用したいのですが、問題が発生しました。現在の多くのプロジェクトでは、インターフェイスのパラメーターとして生のポインターをまだ使用しており、 QMainWindow::setCentralWidgetなどのスマート ポインター用のインターフェイスはありません。

型の一貫性を保つために、次のget()ようなセグメントから格納されたポインターを渡す必要があります。

QMainWindow win;

std::shared_ptr<QWidget> scrollArea{ std::make_shared<QScrollArea>() };
// QScrollArea is a derived class of QWidget.

win.setCentralWidget(scrollArea.get());

deleteしかし、Qt の他のメソッドがの格納されたポインターに対して演算子を実行するかどうかはわかりませんscrollArea

Qt の一部のメソッドがそれを行うと、メモリ リークやその他の問題が発生しますか?

最新のC++ 標準 CDをチェックしましたが、何も見つかりませんでした。未定義の動作のようです。

これを行うことが未定義の動作であり危険である場合、生のポインターのインターフェイスでスマートポインターを安全に使用する方法はありますか?

4

6 に答える 6

17

一般の場合、そのような方法はありません。使用する「レガシー」インターフェースごとに、そのドキュメントを読んで、それが所有権とどのように相互作用するかを確認する必要があります (これは、stdスマート ポインターがカプセル化するものです)。1 つのオブジェクトは、1 つの所有権スキームによってのみ管理できます。

特に Qt では、スマート ポインターと Qt 管理を混在させることは絶対に安全ではありません。Qt の s 間の親子関係にQObjectは所有権のセマンティクス (親が削除されると子が削除される) が含まれるため、これを他の所有権スキーム (stdスマート ポインターなど) と安全に混在させることはできません。

リンク先のQtドキュメントには、「ウィジェットポインターQMainWindowの所有権を取得し、適切なタイミングで削除する」と明示的に記載されていることに注意してください。

于 2013-05-21T07:53:52.820 に答える
3

QWidget で削除を行うべきではないと思います。

http://qt-project.org/doc/qt-4.8/qmainwindow.html#setCentralWidget

注: QMainWindow はウィジェット ポインターの所有権を取得し、適切なタイミングで削除します。

スマート ポインターを使用する必要がある場合は、それを所有または破棄しないweak_ptrを使用できます。

于 2013-05-21T07:56:18.090 に答える
3

残念ながら、生のポインターを使用するインターフェイスを使用している場合は、ドキュメントを参照して、メソッドが提供されたポインターの所有権を取得するかどうかを判断する必要があります。

関数が所有権を取得する場合は、呼び出し.release()て所有権を関数に転送する必要があります。関数が所有権を取得しない場合は、オブジェクトを で渡します.get()

于 2013-05-21T07:54:09.637 に答える
3

Qt の一部のメソッドがそれを行うと、メモリ リークやその他の問題が発生しますか?

メモリは結局解放されるので、メモリ リークは発生しません。ただし、QT と の両方がそのメモリshared_ptrを呼び出すdeleteため、適切なヒープ破損 (一般的には UB) が発生する可能性があります。

生ポインタのインターフェースでスマートポインタを安全に使用する方法はありますか?

もちろん。無関係なエンティティに同じメモリを管理させないでください。そのため、可能な場合はunique_ptr代わりに使用することをお勧めしますshared_ptrunique_ptrスマートポインターの制御からメモリを解放するために呼び出すことができるため.release()、QT に制御を渡すことができます。

もちろん、自分でメモリを管理する必要がある場合と、QT がメモリを管理する場合を確認するには、ドキュメントを確認する必要があります。

于 2013-05-21T07:54:39.740 に答える
1

しかし、Qt の他のメソッドが、scrollArea の格納されたポインタに対して operator delete を実行するかどうかはわかりません。

ウィジェットに親がある場合、QT のメモリ管理によってそのオブジェクトが解放されます。その場合、アプリケーションがスマート ポインターを 2 回解放しようとするため、スマート ポインターを使用しないでください。これは未定義の動作です。

于 2013-05-22T06:21:40.833 に答える