変更点Qt Core
Qt 6 における変更点は、フレームワークをより効率的で使いやすくするための意図的な取り組みの結果です。
各リリースにおいて、すべての公開 API についてバイナリおよびソースの互換性を維持するよう努めています。しかし、Qt をより優れたフレームワークにするためには、いくつかの変更は避けられませんでした。
このトピックでは、Qt Core におけるそれらの変更点をまとめ、それらに対処するための指針を示します。
コンテナクラス
QHash、QMultiHash、QSet
qHash() のシグネチャ
カスタム型の場合、QHash およびQMultiHash は、同じ名前空間内にcustom qHash() function を定義することを前提としています。Qt 4 および Qt 5 では、qHash 関数の戻り値およびオプションの 2 番目の引数はuint 型でした。Qt 6 では、size_t 型となっています。
つまり、次のように変更する必要があります。
を
size_t qHash(MyType x, size_t seed);これにより、64ビットプラットフォーム上でQHash 、QMultiHash 、およびQSet が2^32個を超える項目を保持できるようになります。
参照の安定性
Qt 6 におけるQHash 、QMultiHash 、およびQSet の実装は、ノードベースのアプローチから 2 段階のルックアップテーブルへと変更されました。この設計により、ハッシュインスタンスのメモリオーバーヘッドを非常に小さく抑えつつ、優れたパフォーマンスを実現できます。
注意すべき動作の変更点として、新しい実装では、テーブルの拡張が必要になった場合やエントリが削除された場合、ハッシュ内の要素に対する安定した参照が提供されなくなります。このような安定性に依存しているアプリケーションでは、未定義の挙動が発生する可能性があります。
QHash::insertMulti の削除
Qt 5 では、QHash を使用して QHash::insertMulti により多値ハッシュを作成することができ、QMultiHash はQHash から派生していました。
Qt 6 では、両者の型および使用ケースが明確に区別されるようになったため、QHash::insertMulti は削除されました。
QVector、QList
Qt 6以前、QVector とQList は別々のクラスでした。Qt 6ではこれらが統合され、Qt 5のQList の実装は廃止され、両クラスとも更新されたQVector の実装を使用するようになりました。QList が実際の実装を持つクラスであり、QVector はQList へのエイリアス(typedef)です。
QListQt 6 では、QVector の fromVector() および toVector()、ならびに の fromList() および toList() によるデータコピーは行われなくなりました。これらは現在、呼び出し元オブジェクトをそのまま返します。
APIの変更
QListの(ひいてはQVector の)size型の定義が、int からqsizetype に変更されました。size型の変更に伴い、関連するすべてのメソッドのシグネチャがqsizetype を使用するように更新されています。これにより、64ビットプラットフォーム上でQList が2^31個以上の項目を保持できるようになりました。
コードベースを Qt 6 にアップグレードする際、この API の変更により、型変換の絞り込みに関するコンパイラ警告が発生する可能性が高いです。次のようなサンプルコードがある場合:
void myFunction(QList<MyType> &data) {
int size = data.size();
// ...
const int pos = getInsertPosition(size);
data.insert(pos, MyType());
// ...
}この場合、qsizetype を使用するか、auto キーワードを使用するように更新する必要があります:
void myFunction(QList<MyType> &data) {
auto size = data.size();
// ...
const auto pos = getInsertPosition(size);
data.insert(pos, MyType());
// ...
}あるいは、型キャストを使用して、すべてをint またはqsizetype にキャストすることも可能です。
注: Qt 5 と Qt 6 の両方でビルドしたい場合 、バージョン間のシグネチャの違いをカバーするには、`auto` キーワードを使用するのが良い解決策です。
メモリレイアウト
QList には、Qt 6におけるメモリレイアウトに関連する複数の変更が加えられました。
Qt 5 では、sizeof(QList<T>) はポインタ 1 個分のサイズでした。現在では、余分なポインタ間接参照が削除され、QList のデータメンバーはオブジェクト内に直接格納されるようになりました。デフォルトでは、sizeof(QList<T>) のサイズはポインタ 3 個分になると想定してください。
同時に、要素のメモリレイアウトも更新されました。Qt 5 では、特定のオブジェクトがヒープ上に個別に割り当てられ、そのオブジェクトへのポインタがQList に格納されていたのに対し、QList では、要素が常に割り当てられたメモリ領域に直接格納されるようになりました。
特に後者の変更は、大きなオブジェクトに影響を与える点に注意してください。Qt 5 と同様の挙動を得るには、オブジェクトをスマートポインタでラップし、そのスマートポインタをQList に直接格納することができます。この場合、QList の型は Qt 5 のQList<MyLargeObject> とは異なり、QList<MySmartPointer<MyLargeObject>> となります。
参照の安定性
QVector/QList の実装にはいくつかの変更が加えられています。「QVector 」に関連する変更点は、先頭への挿入が最適化されたことです(Qt 5のQList と同様に)。「QList 」に関連する変更点は、要素のメモリレイアウトが簡素化されたことです。
重要:これらの 変更は、参照の安定性に影響を与えます。Qt 6 では、QList が暗黙的に共有されていない場合でも、サイズや容量を変更するメソッドを実行する際は、すべての参照を無効化することを検討する必要があります。この規則の例外については、明示的に文書化されています。
特定の参照の安定性に依存しているアプリケーションは、Qt 6 へアップグレードした際に未定義の挙動を引き起こす可能性があります。もともと、C 互換ではない配列レイアウトを持つ `QVector ` または `QList ` が使用されていたケースには、特に注意を払う必要があります。
Qt6 のビュークラス
概要
Qt6には、いくつかの新しいView クラスが導入されています。既存のQStringView に加え、新たにQByteArrayView が追加され、さらに特化型のQUtf8StringView と、より汎用的なQAnyStringView が続いています。
QStringViewを例としたビュークラスの概要
QStringView クラスは、QString APIの読み取り専用サブセットを用いて、UTF-16文字列に対する統一されたビューを提供します。文字列の独自のコピー(場合によっては参照カウント付き)を保持するQString とは異なり、QStringView は、別の場所に格納されている文字列のビューを提供します。
char hello[]{ "Hello." }; // narrow multi-byte string literal
QString str{hello}; // needs to make a copy of the string literal
QString strToStr(str); // atomic increment involved to not create a copy of hello again
// The above code can be re-written to avoid copying and atomic increment.
QStringView view{ u"Hello." }; // view to UTF-16 encoded string literal
QStringView viewToView{ view }; // view of the same UTF-16 encoded string literal文字列"Hello." はバイナリに格納されており、実行時に割り当てられることはありません。view は、文字列"Hello." に対するビューに過ぎないため、コピーを作成する必要はありません。QStringView をコピーする場合、viewToView は、コピー元のview が参照しているのと同じ文字列を参照します。つまり、viewToView はコピーを作成したり、アトミックなインクリメントを行ったりする必要がありません。これらは、既存の文字列"Hello." に対するビューです。
関数の引数としてのビュー
ビューは、constへの参照ではなく、値渡しで渡されるべきです。
void myfun1(QStringView sv); // preferred
void myfun2(const QStringView &sv); // compiles and works, but slowerビュー操作関数
QStringView は、文字列のビューを操作できる関数をサポートしています。これにより、ビュー対象の文字列の部分コピーを作成することなく、ビューを変更することが可能です。
QString pineapple = "Pineapple";
QString pine = pineapple.left(4);
// The above code can be re-written to avoid creating a partial copy.
QStringView pineappleView{ pineapple };
QStringView pineView = pineappleView.left(4);ヌル終端されていない文字列および'\0'
QStringView ヌル終端文字付き文字列とヌル終端でない文字列の両方をサポートしています。違いは、QStringView の初期化方法にあります:
QChar aToE[]{ 'a', 'b', 'c', 'd', 'e' };
QStringView nonNull{ aToE, std::size(aToE) }; // with length given
QStringView nonNull{ aToE }; // automatically determines the length
QChar fToJ[]{ 'f', 'g', 'h', '\0', 'j' };
// uses given length, doesn't search for '\0', so '\0' at position 3
// is considered to be a part of the string similarly to 'h' and 'j
QStringView nonNull{ fToJ, std::size(fToJ) };
QStringView part{ fToJ }; //stops on the first encounter of '\0'ビューの所有権モデル
views は、参照するメモリを所有していないため、すべてのコードパスにおいて、参照されるデータ(例えば、QString が所有するデータ)がview よりも長く存続するように注意を払う必要があります。
QStringView sayHello()
{
QString hello("Hello.");
return QStringView{ hello }; // hello gets out of scope and destroyed
}
void main()
{
QStringView hello{ sayHello() };
qDebug() << hello; // undefined behavior
}QStringViewをQStringに変換する
QStringView は、暗黙的にも明示的にもQString に変換されることはありませんが、そのデータのディープコピーを作成する可能性があります:
void print(const QString &s) { qDebug() << s; }
void main()
{
QStringView string{ u"string"};
// print(string); // invalid, no implicit conversion
// QString str{ string }; // invalid, no explicit conversion
print(string.toString());
QString str = string.toString(); // create QString from view
}重要な注意事項
新しいビュークラスを活用することで、多くのユースケースにおいて大幅なパフォーマンス向上を実現できます。ただし、いくつかの注意点があることを理解しておくことが重要です。したがって、以下の点を覚えておくことが重要です:
- ビューは、constへの参照ではなく、値渡しで渡す必要があります。
- 負の長さでビューを構築することは、未定義の挙動となります。
- 参照されるデータ(例:QString が所有するデータ)が、すべてのコードパスにおいてビューよりも長く存続するように注意を払う必要があります。
文字列関連のクラス
QStringView クラス
Qt6 以降では、一般的にQStringRef よりもQStringView を使用することが推奨されています。QStringView は、自身が所有していない UTF-16 文字列の連続した部分を参照します。これは、最初にQString を構築する必要なく、あらゆる種類の UTF-16 文字列に対するインターフェース型として機能します。QStringView クラスは、QString および以前に存在したQStringRef クラスのほぼすべての読み取り専用メソッドを公開しています。
注: 参照される文字列データ(例えば、QString が所有するもの)が、すべてのコードパスにおいてQStringView よりも長く存続するように注意 する必要があります。
注: QStringView がQString をラップしている場合 、QStringRef とは異なり、QStringView はQString データが再配置された後も内部データポインタを更新しないため、注意が必要です。
QString string = ...;
QStringView view{string};
// Appending something very long might cause a relocation and will
// ultimately result in a garbled QStringView.
string += ...;QStringRefクラス
Qt6では、QStringRef がQt Core から削除されました。既存のアプリケーションをコードベース全体を変更せずに移植しやすくするため、QStringRef クラスは完全に廃止されることなく、代わりにQt5Compatモジュールに移動されました。QStringRef を引き続き使用したい場合は、「Qt5Compatモジュールの使用」を参照してください。
残念ながら、QString が公開し、QStringRef を返す一部のメソッドは、Qt5Compatへ移行することができませんでした。そのため、手動での移植が必要になる場合があります。コードで以下の関数のいずれかを使用している場合は、QStringView またはQStringTokenizer を使用するように移植する必要があります。また、パフォーマンスが重要なコードでは、QStringView::split の代わりにQStringView::tokenize を使用することを推奨します。
QStringRef を使用しているコードを次のように変更してください:
QString string = ...;
QStringRef left = string.leftRef(n);
QStringRef mid = string.midRef(n);
QStringRef right = string.rightRef(n);
QString value = ...;
const QVector<QStringRef> refs = string.splitRef(' ');
if (refs.contains(value))
return true;を次のように変更します:
QString string = ...;
QStringView left = QStringView{string}.left(n);
QStringView mid = QStringView{string}.mid(n);
QStringView right = QStringView{string}.right(n);
QString value = ...;
const QList<QStringView> refs = QStringView{string}.split(u' ');
if (refs.contains(QStringView{value}))
return true;
// or
const auto refs = QStringView{string}.tokenize(u' ');
for (auto ref : refs) {
if (ref == value)
return true;
}QMutex および関連クラス
Qt 6 では、QRecursiveMutex はもはやQMutex を継承していません。この変更は、QMutex およびQRecursiveMutex の両方のパフォーマンスを向上させるために行われました。
これらの変更に伴い、QMutex::RecursionMode 列挙型は削除され、QMutexLocker はQMutex とQRecursiveMutex の両方で動作可能なテンプレートクラスとなりました。
QFuture および関連クラス
QFuture クラス
QFuture の意図しない使用を避けるため、Qt 6 ではQFuture API にいくつかの変更が加えられ、ソース互換性が損なわれる可能性があります。
QFuture と他の型間の暗黙の変換
QFuture<T> からT への変換は無効化されました。キャスト演算子はQFuture::result() を呼び出していました。これは、ユーザーが変換を試みる前にQFuture の結果をQFuture::takeResult() を通じて移動させていた場合、未定義の挙動を引き起こす可能性があります。QFuture<T> をT に変換する必要がある場合は、明示的にQFuture::result() またはQFuture::takeResult() メソッドを使用してください。
QFuture<T> からQFuture<void> への暗黙的な変換も無効化されました。どうしても変換を行いたい場合は、明示的なQFuture<void>(const QFuture<T> &) コンストラクタを使用してください:
等価演算子
QFuture の等価性演算子が削除されました。これらは結果を比較するのではなく、基になる d-ポインタを比較していたため、ユーザーの期待に沿わない動作となっていました。QFuture オブジェクトを比較する必要がある場合は、QFuture::result() またはQFuture::takeResult() メソッドを使用してください。例:
QFuture<int> future1 = ...;
QFuture<int> future2 = ...;
if (future1.result() == future2.result())
// ...QFuture および QFutureWatcher の動作変更
Qt 6 では、QFuture およびQFutureWatcher にいくつかの改善が加えられ、その結果、以下の動作の変更が生じました:
- QFuture またはQFutureWatcher を一時停止した後(
pause()またはsetPaused(true)を呼び出すことで)、QFutureWatcher は直ちに進行状況および結果の ready シグナルの配信を停止しません。一時停止の時点では、まだ進行中で停止できない計算が残っている可能性があります。 そのような計算に関するシグナルは、一時停止後に遅延されて次の再開時にのみ報告されるのではなく、一時停止後も引き続き配信される可能性があります。一時停止が実際に有効になったことを通知を受けるには、QFutureWatcher::suspended() シグナルを使用できます。さらに、QFuture が一時停止の処理中であるか、すでに一時停止状態にあるかを確認するための新しいメソッドisSuspending()およびisSuspended()が用意されています。 なお、一貫性を保つため、QFuture およびQFutureWatcher の両方において、一時停止関連のAPIは非推奨となり、代わりに名前に「suspend」を含む類似のメソッドに置き換えられました。 - QFuture::waitForFinished() は、QFuture が実行中状態でなくなるとすぐに終了するのではなく、実際に完了状態になるまで待機するようになりました。これにより、呼び出し時点でフューチャーがまだ開始されていない場合でも、
waitForFinished()が即座に終了することを防ぎます。QFutureWatcher::waitForFinished() についても同様です。この変更は、QFuture をQtConcurrent と組み合わせて使用していたコードの動作には影響しません。影響を受ける可能性があるのは、非公開のQFutureInterfaceと組み合わせて使用していたコードのみです。 - QFutureWatcher::isFinished() は、QFutureWatcher::finished() が発行されるまで false を返すのではなく、QFuture の完了状態を反映するようになりました。
QPromise クラス
Qt 6 では、QFuture の「セッター」としての対応物として、非公式の QFutureInterface の代わりに新しいQPromise クラスを使用する必要があります。
IO クラス
QProcess クラス
Qt 6 では、単一のコマンド文字列をプログラム名と引数に分割して解釈する `QProcess::start()` のオーバーロードは、`QProcess::startCommand()` に名称が変更されました。ただし、単一の文字列を受け取る `QProcess::start()` のオーバーロードや、引数用の `QStringList ` は引き続き存在します。QStringList パラメータのデフォルト値は空のリストであるため、文字列のみを渡す既存のコードは引き続きコンパイルされますが、引数を含む完全なコマンド文字列である場合は、プロセスの実行に失敗します。
Qt 5.15 では、既存のコードを容易に特定・更新できるよう、当該オーバーロードに対して非推奨警告が導入されました:
QProcess process;
// compiles with warnings in 5.15, compiles but fails with Qt 6
process.start("dir \"My Documents\"");
// works with both Qt 5 and Qt 6; also see QProcess::splitCommand()
process.start("dir", QStringList({"My Documents"});
// works with Qt 6
process.startCommand("dir \"My Documents\"");QProcess::pid() および Q_PID 型は削除されました。ネイティブのプロセス識別子を取得するには、代わりにQProcess::processId() を使用してください。Q_PID 内のデータに、Win32 のPROCESS_INFORMATION 構造体としてアクセスするためにネイティブの Win32 API を使用するコードは、もはやサポートされません。
メタタイプシステム
QVariant クラス
QVariant は、すべての操作で `QMetaType ` を使用するように書き換えられました。これにより、いくつかのメソッドの挙動が変更されています:
QVariant::isNull()は、QVariantが空であるか、nullptrを含む場合にのみtrueを返すようになりました。Qt 5では、qtbase内のクラスで、isNullメソッド自体があり、かつそのメソッドがtrueを返す場合にもtrueを返していました。 従来の挙動に依存するコードでは、含まれる値が `isNull` を返すかどうかを確認する必要があります。ただし、isNull()が関心のあるプロパティであることはめったにないため、実際にはそのようなコードが存在する可能性は低いでしょう(QString::isEmpty()やisNull()と、QTime::isValidやisNullを比較してください)。QVariant::operator==Qt 6ではQMetaType::equalsが使用されます。そのため、適切な等価演算子を持たない一部の型(QPixmapやQIconなど)は、決して等しいと判定されません。さらに、QVariantに格納された浮動小数点数は、qFuzzyCompareによる比較が行われなくなり、代わりに厳密な比較が行われるようになりました。
さらに、異なるバリアントは必ずしも順序付け可能ではないため、QVariant::operator<、QVariant::operator<=、QVariant::operator>、および QVariant::operator>= は削除されました。これは、QVariant がQMap のキーとして使用できなくなったことも意味します。
QMetaType クラス
Qt 6 では、比較関数およびQDebug およびQDataStream ストリーミング演算子の登録が自動的に行われます。その結果、QMetaType::registerEqualsComparator() 、QMetaType::registerComparators() 、qRegisterMetaTypeStreamOperators() 、およびQMetaType::registerDebugStreamOperator() は存在しなくなりました。Qt 6 への移植時には、これらのメソッドへの呼び出しを削除する必要があります。
型の登録
Q_PROPERTY で使用される型のメタ型は、クラスのQMetaObject に格納されます。これにより、mocが型を検出する際に型が完全である必要があり、Qt 5では動作していたコードでもコンパイルエラーが発生する可能性があります。この問題を解決するには、次の3つの方法があります:
- その型を定義するヘッダーをインクルードする。
- インクルードの代わりに、
Q_MOC_INCLUDEマクロを使用する。これは、ヘッダーをインクルードすると循環依存関係が発生する場合や、コンパイル速度が低下する場合に有効です。 - クラスを実装する cpp ファイル内にヘッダーファイルが存在する場合、そこに moc によって生成されたファイルを含めることも可能です。
正規表現クラス
QRegularExpression クラス
Qt 6 では、QRegExp 型は Qt5Compat モジュールに移行され、これを使用していたすべての Qt API は他のモジュールから削除されました。これを使用していたクライアントコードは、代わりにQRegularExpression を使用するように移植できます。QRegularExpression はすでに Qt 5 に存在するため、Qt 6 への移行前にこの変更を行い、テストを行うことができます。
Qt 5で導入されたQRegularExpression クラスは、Perl互換の正規表現を実装しており、提供されるAPI、サポートされるパターン構文、および実行速度の点で、QRegExp に比べて大幅な改善が図られています。 最大の違いは、QRegularExpression が単に正規表現を保持しているだけであり、一致のチェックが要求されてもその内容に変更が加わらない点です。代わりに、一致の結果を確認し、キャプチャされた部分文字列を抽出するために、QRegularExpressionMatch オブジェクトが返されます。これは、グローバルマッチングやQRegularExpressionMatchIterator についても同様です。
その他の違いについては、以下に概要を示します。
注: QRegularExpression は、 Perl互換正規表現で利用可能なすべての機能をサポートしているわけではありません。最も顕著な点は、キャプチャグループの重複した名前がサポートされていないことであり、これらを使用すると未定義の挙動を引き起こす可能性があります。これは将来のQtのバージョンで変更される可能性があります。
異なるパターン構文
QRegExp からQRegularExpression へ正規表現を移植する際には、パターン自体の変更が必要になる場合があります。
特定のシナリオでは、QRegExp は許容範囲が広すぎたため、QRegularExpression では単純に無効となるパターンも受け入れられていました。これらは、これらのパターンで構築されたQRegularExpression オブジェクトが無効となるため、容易に検出できます(QRegularExpression::isValid() を参照)。
また、QRegExp からQRegularExpression へ移植されたパターンによっては、意味論が黙って変更される場合があります。そのため、使用されているパターンを再確認する必要があります。黙って生じる非互換性の最も顕著な例は以下の通りです:
\xHHHHのような 2 桁を超える 16 進エスケープを使用するには、中括弧が必要です。\x2022のようなパターンは、\x{2022}に移植する必要があります。そうしないと、スペース (0x20) の後に文字列"22"が続く場合にも一致してしまいます。一般に、指定された桁数にかかわらず、\xエスケープには常に中括弧を使用することを強く推奨します。{,n}のような 0 から n までの定量化は、意味論を維持するために{0,n}へ変換する必要があります。そうしないと、\d{,3}のようなパターンは、数字の後に「"{,3}"」という正確な文字列が続く場合に一致してしまいます。- QRegExp デフォルトではUnicodeを意識したマッチングが行われますが、QRegularExpression では別途オプションが必要です。詳細については以下を参照してください。
- QRegExp における c{.} は、デフォルトで改行文字を含むすべての文字に一致します。QRegularExpression は、デフォルトで改行文字を除外します。改行文字を含めるには、QRegularExpression::DotMatchesEverythingOption パターンオプションを設定してください。
QRegularExpression がサポートする正規表現構文の概要については、PCRE(Perl互換正規表現のリファレンス実装)がサポートするパターン構文を説明したpcrepattern(3)のマニュアルページを参照してください。
QRegExp::exactMatch()からの移植
QRegExp::exactMatch()からの移植には2つの目的がありました。それは、対象文字列に対して正規表現を完全に一致させることと、部分一致を実装することでした。
QRegExp の完全一致からの移植
完全一致とは、正規表現が対象文字列全体と一致するかどうかを示すものです。たとえば、対象文字列 `"abc123"` に対して、以下のクラスが得られます:
| QRegExp::exactMatch() | QRegularExpressionMatch::hasMatch() | |
|---|---|---|
"\\d+" | false | true |
"[a-z]+\\d+" | true | true |
QRegularExpression では完全一致は反映されません。対象文字列が正規表現と完全に一致することを確実にしたい場合は、QRegularExpression::anchoredPattern()関数を使用してパターンを囲むことができます:
QString p("a .*|pattern");
// re matches exactly the pattern string p
QRegularExpression re(QRegularExpression::anchoredPattern(p));QRegExpの部分一致からの移行
QRegExp::exactMatch() を使用する場合、完全一致が見つからなかったとしても、QRegExp::matchedLength() を呼び出すことで、対象文字列のうち正規表現と一致した部分がどの程度あったかを確認することができました。返された長さが対象文字列の長さと等しかった場合、部分一致が見つかったと判断することができました。
QRegularExpression は、適切なQRegularExpression::MatchType を用いて、部分一致を明示的にサポートしています。
グローバルマッチング
QRegExp API の制限により、グローバルマッチングを(Perl と同様に)正しく実装することは不可能でした。特に、0 文字にマッチするパターン("a*" など)は問題となります。
QRegularExpression::globalMatch() は Perl のグローバルマッチングを正しく実装しており、返されるイテレータを使用して各結果を調べることができます。
たとえば、次のようなコードがある場合:
QString subject("the quick fox");
int offset = 0;
QRegExp re("(\\w+)");
while ((offset = re.indexIn(subject, offset)) != -1) {
offset += re.matchedLength();
// ...
}次のように書き換えることができます:
QString subject("the quick fox");
QRegularExpression re("(\\w+)");
QRegularExpressionMatchIterator i = re.globalMatch(subject);
while (i.hasNext()) {
QRegularExpressionMatch match = i.next();
// ...
}Unicodeプロパティのサポート
QRegExp を使用する場合、\w 、\d などの文字クラスは、対応するUnicodeプロパティを持つ文字に一致します。たとえば、\d は、UnicodeのNd (10進数字)プロパティを持つ任意の文字に一致します。
QRegularExpression を使用する場合、これらの文字クラスはデフォルトではASCII文字にのみ一致します。例えば、\d は、0-9 のASCII範囲内の文字にのみ正確に一致します。この挙動は、QRegularExpression::UseUnicodePropertiesOption パターンオプションを使用することで変更可能です。
ワイルドカードマッチング
QRegularExpression では、ワイルドカードマッチングを直接行う方法はありません。ただし、QRegularExpression::wildcardToRegularExpression() メソッドが用意されており、glob パターンをその目的で使用できる Perl 互換の正規表現に変換することができます。
たとえば、次のようなコードがあるとします:
次のように書き換えることができます:
auto wildcard = QRegularExpression(QRegularExpression::wildcardToRegularExpression("*.txt"));ただし、一部のシェル風のワイルドカードパターンは、期待どおりの形式に変換されない場合があることに注意してください。次のサンプルコードは、前述の関数を使って単純に変換すると、何の警告もなく動作しなくなります:
const QString fp1("C:/Users/dummy/files/content.txt");
const QString fp2("/home/dummy/files/content.txt");
QRegExp re1("*/files/*");
re1.setPatternSyntax(QRegExp::Wildcard);
re1.exactMatch(fp1); // returns true
re1.exactMatch(fp2); // returns true
// but converted with QRegularExpression::wildcardToRegularExpression()
QRegularExpression re2(QRegularExpression::wildcardToRegularExpression("*/files/*"));
re2.match(fp1).hasMatch(); // returns false
re2.match(fp2).hasMatch(); // returns falseこれは、デフォルトでは `QRegularExpression::wildcardToRegularExpression()` が返す正規表現が完全にアンカーされているためです。アンカーされていない正規表現を取得するには、変換オプションとして `QRegularExpression::UnanchoredWildcardConversion ` を指定してください:
QRegularExpression re3(QRegularExpression::wildcardToRegularExpression(
"*/files/*", QRegularExpression::UnanchoredWildcardConversion));
re3.match(fp1).hasMatch(); // returns true
re3.match(fp2).hasMatch(); // returns true最小限のマッチング
QRegExp::setMinimal() は、量指定子の貪欲性を単に反転させることで最小一致を実装していました(QRegExp は、*? や+? などの遅延量指定子をサポートしていませんでした)。一方、QRegularExpression は、貪欲、遅延、および所有量指定子をサポートしています。QRegularExpression::InvertedGreedinessOption というパターンオプションは、QRegExp::setMinimal()の効果をエミュレートするのに役立ちます。これを有効にすると、量指定子の貪欲性が反転します(貪欲なものが遅延型になり、その逆も同様です)。
キャレットモード
QRegularExpression::AnchorAtOffsetMatchOption マッチングオプションを使用すると、QRegExp::CaretAtOffset の挙動をエミュレートできます。その他のQRegExp::CaretMode モードに相当する機能はありません。
QRegExp クラス
Qt6では、Qt Core からQRegExp が削除されました。現時点でアプリケーションを移植できない場合、これらのコードベースが引き続き動作するよう、QRegExp はQt5Compat内に残されています。QRegExp を引き続き使用したい場合は、「Qt5Compatモジュールの使用」を参照してください。
QEvent およびそのサブクラス
QEvent クラスは、多態的なクラスであるにもかかわらず、コピーコンストラクタと代入演算子を定義していました。仮想メソッドを持つクラスをコピーすると、異なるクラスのオブジェクトを互いに代入する際にスライシングが発生する可能性があります。コピーや代入はしばしば暗黙的に行われるため、これはデバッグが困難な問題につながる恐れがあります。
Qt 6 では、QEvent のサブクラスのコピーコンストラクタと代入演算子が protected に変更され、暗黙的なコピーが防止されるようになりました。 イベントをコピーする必要がある場合は、clone メソッドを使用してください。このメソッドは、QEvent オブジェクトのヒープ上に割り当てられたコピーを返します。クローンしたオブジェクトを削除する場合は、std::unique_ptrなどを使用して確実に削除してください(ただし、ポスト(post)する場合は、Qtが配信後に自動的に削除します)。
QEvent のサブクラスでは、clone()をオーバーライドし、保護されたデフォルト実装のコピーコンストラクタおよび代入演算子を次のように宣言してください。
class MyEvent : public QEvent
{
public:
// ...
MyEvent *clone() const override { return new MyEvent(*this); }
protected:
MyEvent(const MyEvent &other) = default;
MyEvent &operator=(const MyEvent &other) = default;
MyEvent(MyEvent &&) = delete;
MyEvent &operator=(MyEvent &&) = delete;
// member data
};なお、MyEvent クラスが(例えば、実装へのポインタパターンを通じて)メモリを割り当てている場合は、カスタムなコピーセマンティクスを実装する必要があります。
シリアライゼーションクラス
Qt 6 では、Qt のレガシーな JSON バイナリ形式との相互変換を行うQJsonDocument メソッドが削除され、標準化された CBOR 形式が採用されました。Qt JSON 型は Qt CBOR 型に変換でき、さらに CBOR バイナリ形式にシリアライズしたり、その逆の変換を行ったりすることができます。例として、QCborValue::fromJsonValue() やQCborValue::toJsonValue() を参照してください。
それでもバイナリ JSON 形式を使用する必要がある場合は、Qt5Compat モジュールで提供されている代替機能を利用できます。これらはQBinaryJson 名前空間にあります。アプリケーションでのモジュールの使用方法については、「Qt5Compat モジュールの使用」を参照してください。
その他のクラス
Qt 5 では、QCoreApplication::quit() はQCoreApplication::exit() を呼び出すのと同じ動作をしていました。これは単にメインイベントループを終了させるだけのものでした。
Qt 6 では、このメソッドは代わりに、閉じるイベントを送信することで、すべてのトップレベルウィンドウを閉じようと試みます。ウィンドウ側は、そのイベントを無視することで、シャットダウン処理をキャンセルすることができます。
従来の無条件の動作を維持するには、QCoreApplication::exit() を呼び出してください。
QLibraryInfo::location() および QLibraryInfo::Location は、命名規則に一貫性がないため非推奨となりました。代わりに、新しい API であるQLibraryInfo::path() およびQLibraryInfo::LibraryPath を使用してください。
Qt State Machine Framework
Qt State Machine はQt SCXML モジュール(まもなく Qt State Machine に名称変更予定)に移行されたため、Qt Core の一部ではなくなりました。Qt Core 内部の相互依存関係が極めて少なかったことが、最終的にこの決定につながりました。
Qt5Compatモジュールの使用方法
Qt5Compatモジュールを使用するには、インクルードパスにそのヘッダーを含めてビルドし、そのライブラリに対してリンクする必要があります。qmakeを使用している場合は、.pro ファイルに以下を追加してください:
QT += core5compatcmake を使用してアプリケーションやライブラリをビルドする場合は、CMakeList.txt に以下を追加してください:
PUBLIC_LIBRARIES
Qt::Core5CompatQTextStream
QTextStream::setCodec() を削除しました。代わりに、新しい Encoding 列挙型を使用したQTextStream::setEncoding() を使用してください。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.