Qt コアの変更点

Qt 6 は、フレームワークをより効率的で使いやすくするための意識的な努力の結果です。

私たちは各リリースにおいて、すべてのパブリックAPIのバイナリとソースの互換性を維持しようと努めています。しかし、Qt をより良いフレームワークにするために避けられない変更もあります。

このトピックでは、Qt Core におけるそれらの変更点を要約し、それらを扱うためのガイダンスを提供します。

コンテナクラス

QHash, QMultiHash, QSet

qHash() シグネチャ

カスタム型の場合、QHashQMultiHash は、同じ名前空間にcustom qHash() function を提供することに依存します。Qt 4 と Qt 5 では、qHash 関数の戻り値とオプションの第 2 引数はuint 型でした。Qt 6 ではsize_t です。

つまり

uint qHash(MyType x, uint seed);

に変更する必要があります。

size_t qHash(MyType x, size_t seed);

これにより、QHashQMultiHashQSet は、64ビット・プラットフォームで2^32以上のアイテムを保持できるようになります。

参照の安定性

Qt 6 のQHash,QMultiHash,QSet の実装は、ノードベースのアプローチから、2ステージのルックアップテーブルに変更されました。この設計により、ハッシュ・インスタンスのメモリ・オーバーヘッドを非常に小さく保つことができ、同時にパフォーマンスも向上しています。

注意すべき動作上の変更点として、新しい実装では、テーブルが大きくなったり、エントリーが削除されたりしたときに、ハッシュ内の要素への安定した参照が提供されないという点がある。このような安定性に依存しているアプリケーションでは、未定義の動作が発生する可能性があります。

QHash::insertMulti の削除

Qt 5 では、QHash は QHash::insertMulti を使用して多値ハッシュを作成することができ、QMultiHash は vomQHash に派生していました。

Qt 6 では、両方の型とユースケースが区別され、QHash::insertMulti は削除されました。

QVector, QList

Qt 6 以前では、QVectorQList は別々のクラスでした。Qt 6 では統一されました:Qt 5 のQList の実装はなくなり、代わりに両方のクラスが更新されたQVector の実装を使用しています。QList が実際の実装を持つクラスで、QVectorQList のエイリアス(typedef)です。

QListQt 6 では、fromVector() と toVector()、およびQVector の fromList() と toList() は、データのコピーを伴わなくなりました。これらは、呼び出されたオブジェクトを返すようになりました。

API の変更

QList QVector int から にサイズ型が変更されました。サイズ型とともに、関連するすべてのメソッドのシグネチャが を使用するように更新されました。これにより、 は 64 ビット・プラットフォームで 2^31 個以上のアイテムを保持できるようになります。qsizetype qsizetype QList

コードベースを 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>) はポインタのサイズに等しかったです。現在では、余分なポインタのインダイレクトは削除され、QList のデータメンバーはオブジェクトに直接格納されます。デフォルトでは、sizeof(QList<T>) は3つのポインタのサイズに等しくなります。

同時に、要素のメモリレイアウトも更新されます。QList は、Qt 5 では特定のオブジェクトがヒープ上に個別に割り当てられ、そのオブジェクトへのポインタが代わりに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 互換でない配列レイアウトのQVectorQList が元々使用されていた場合は特に注意が必要です。

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 よりも長生きするように注意する必要があります。

注: QStringViewQString をラップする場合、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 をさらに使いたい場合は、Using the Qt5Compat module を参照してください。

残念ながら、QStringRef を返すQString によって公開されているいくつかのメソッドは、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;
}

Qt 6 では、QRecursiveMutexQMutex を継承しなくなりました。この変更は、QMutexQRecursiveMutex のパフォーマンスを向上させるために行われました。

これらの変更により、QMutex::RecursionMode 列挙型は削除され、QMutexLocker は、QMutexQRecursiveMutex の両方で操作できるテンプレート化されたクラスになりました。

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<int> future = ...
QFuture<void> voidFuture = QFuture<void>(future);

等式演算子

QFuture の等式演算子は削除されました。これらの演算子は、結果を比較するのではなく、基礎となるdポインタを比較していました。QFuture オブジェクトを比較する必要がある場合は、QFuture::result() またはQFuture::takeResult() メソッドを使用してください。例えば

QFuture<int> future1 = ...;
QFuture<int> future2 = ...;
if (future1.result() == future2.result())
    // ...

QFuture と QFutureWatcher の動作変更

Qt 6 では、QFutureQFutureWatcher に改良が加えられ、次のような動作の変更がありました:

  • QFuture またはQFutureWatcher を一時停止した後(pause() またはsetPaused(true) を呼び出した後)、QFutureWatcher は進行状況および結果準備完了シグナルの配信を直ちに停止しない。一時停止の時点で、まだ進行中で停止できない計算があるかもしれない。そのような計算のシグナルは、一時停止後も配信される可能性があります。一時停止が実際に有効になったことを通知するには、QFutureWatcher::suspended() シグナルを使用することができる。さらに、isSuspending()isSuspended() メソッドが新たに追加され、QFuture が一時停止中か、すでに一時停止状態かをチェックできるようになった。一貫性を保つため、QFutureQFutureWatcher の一時停止関連APIは非推奨となり、代わりに名前に「suspend」を持つ同様のメソッドに置き換えられました。
  • QFuture::waitForFinished() は、QFuture が実行状態でなくなるとすぐに終了するのではなく、実際に終了状態になるまで待つようになった。これにより、waitForFinished() を呼び出した時点で未来がまだ開始されていない場合、すぐに終了してしまうことを防ぐことができる。QFutureWatcher::waitForFinished() も同様である。この変更は、QtConcurrent とともにQFuture を使用していたコードの動作には影響しません。影響を受けるのは、文書化されていないQFutureInterface
  • QFutureWatcher::isFinished() は、QFutureWatcher::finished() が発行されるまで false を返すのではなく、QFuture の終了状態を反映するようになりました。

QPromise クラス

Qt 6 では、QFuture の "セッター "として、非公式な QFutureInterface の代わりに、新しいQPromise クラスを使用する必要があります。

IOクラス

QProcess クラス

Qt 6 では、1 つのコマンド文字列をプログラム名と引数に分割して解釈する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() を使用してください。Win32のPROCESS_INFORMATION 構造体としてQ_PIDのデータにアクセスするためにネイティブWin32 APIを使用するコードはサポートされなくなりました。

メタ型システム

QVariant クラス

QVariant クラスは、すべての操作に を使用するように書き換えられました。これにより、いくつかのメソッドの動作が変更されます:QMetaType

  • QVariant::isNull() true QVariant nullptrQt 5 では、 メソッドを持つ qtbase のクラスが真を返した場合、そのクラス自身も真を返していました。古い動作に依存するコードは、含まれる値が isNull を返すかどうかをチェックする必要があります - しかし、 が興味のあるプロパティであることはほとんどないため、そのようなコードは実際には発生しません( / と / を比較してください)。isNull isNull() QString::isEmpty() isNull() QTime::isValid isNull
  • QVariant::operator== Qt 6では 。そのため、 、 、 のようなグラフィカルな型は、決して等しく比較されません。さらに、 に格納された浮動小数点数は、 と比較されなくなり、代わりに正確な比較が使用されます。QMetaType::equals QPixmap QImage QIcon QVariant qFuzzyCompare

さらに、QVariant::operator<、QVariant::operator<=、QVariant::operator>、QVariant::operator>=は削除されました。これはまた、QMap のキーとしてQVariant を使用できないことを意味します。

QMetaType クラス

Qt 6 では、比較演算子、QDebugQDataStream ストリーミング演算子の登録は自動的に行われます。その結果、QMetaType::registerEqualsComparator()QMetaType::registerComparators()qRegisterMetaTypeStreamOperators()QMetaType::registerDebugStreamOperator() はもはや存在しません。Qt 6に移植する際には、これらのメソッドへの呼び出しを削除する必要があります。

型の登録

Q_PROPERTY で使用される型は、そのメタ型がクラスのQMetaObject に格納されています。このため、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 patternオプションを設定する。

QRegularExpression でサポートされている正規表現の構文の概要については、 PCRE (Perl 互換正規表現のリファレンス実装) でサポートされているパターン構文を説明したpcrepattern(3)man ページを参照してください。

QRegExp::exactMatch()からの移植

QRegExp::exactMatch() は二つの目的を果たしました: 正規表現と対象文字列を正確にマッチさせることと、 部分マッチを実装することです。

QRegExp の完全一致からの移植

正確なマッチングは、正規表現が対象文字列全体にマッチするかどうかを示します。例えば、"abc123"

QRegExp::exactMatch()QRegularExpressionMatch::hasMatch()
"\\d+"false
"[a-z]+\\d+"

完全マッチングはQRegularExpression には反映されません。 subject 文字列が正規表現に正確にマッチすることを確認したい場合は、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();
    // ...
}

ユニコード・プロパティのサポート

QRegExp を使う場合、\w\d などの文字クラスは、対応する Unicode プロパティを持つ文字にマッチします。例えば、\d は、UnicodeNd (10進数) プロパティを持つ文字にマッチします。

これらの文字クラスは、QRegularExpression を使用する場合、デフォルトでは ASCII 文字にのみマッチします:例えば、\d0-9 ASCII 範囲の文字に正確にマッチします。この動作を変更するには、QRegularExpression::UseUnicodePropertiesOption patternオプションを使用します。

ワイルドカード・マッチング

QRegularExpression でワイルドカード・マッチングを行う直接的な方法はありません。 しかし、QRegularExpression::wildcardToRegularExpression() メソッドが用意されており、グロブ・パターンを Perl 互換の正規表現に変換して使用することができます。

例えば、:

QRegExp wildcard("*.txt");
wildcard.setPatternSyntax(QRegExp::Wildcard);

のように書き換えることができる:

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 は、*?+? などのような、lazy quantifiers をサポートしていません。QRegularExpression は、代わりに greedy, lazy, possessive quantifiers をサポートしています。QRegularExpression::InvertedGreedinessOption パターンオプションは、QRegExp::setMinimal() の効果をエミュレートするのに便利です。有効にすると、量化子の貪欲さが反転します(貪欲なものは怠惰になり、その逆も同様です)。

キャレットモード

QRegExp::CaretAtOffset の動作をエミュレートするにはQRegularExpression::AnchorAtOffsetMatchOption match オプションを使用します。他のQRegExp::CaretMode モードに相当するものはありません。

QRegExp クラス

Qt6 ではQRegExp が Qt Core から削除されました。あなたのアプリケーションが今すぐ移植できない場合、QRegExp はまだ Qt5Compat に存在し、これらのコードベースを動作させ続けることができます。QRegExp をさらに使用したい場合は、Qt5Compat モジュールを使用する を参照してください。

QEventとサブクラス

QEvent クラスは、ポリモーフィックなクラスであるにもかかわらず、コピーコンストラクタと代入演算子を定義しました。仮想メソッドを持つクラスをコピーすると、異なるクラスのオブジェクトを互いに代入するときにスライシングが発生する可能性があります。コピーや代入は暗黙的に行われることが多いので、デバッグが難しい問題につながる可能性があります。

Qt 6 では、QEvent サブクラスのコピーコンストラクタと代入演算子は、暗黙的なコピーを防ぐために保護されています。イベントをコピーする必要がある場合は、clone メソッドを使用してください。 メソッドは、QEvent オブジェクトのヒープに割り当てられたコピーを返します。クローンを投稿しない限り(その場合、Qtは投稿されたクローンを削除します)、クローンを削除してください(おそらくstd::unique_ptrを使用します)。

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 では、標準化された CBOR フォーマットのために、Qt のレガシーな JSON バイナリフォーマットとの間で変換するためのQJsonDocument メソッドが削除されました。Qt JSON型はQt CBOR型に変換することができ、CBORバイナリフォーマットにシリアライズすることができます。例えば、QCborValue::fromJsonValue() やQCborValue::toJsonValue() を参照してください。

それでもバイナリJSONフォーマットを使用する必要がある場合は、Qt5Compatモジュールで提供されている置換を使用することができます。これらはQBinaryJson 名前空間にあります。Qt5Compat モジュールをアプリケーションで使用する方法についてはUsing the Qt5Compat moduleを参照してください。

その他のクラス

Qt 5 では、QCoreApplication::quit() はQCoreApplication::exit() を呼び出すのと同じでした。これはメイン・イベント・ループを抜けるだけです。

Qt 6では、このメソッドはcloseイベントをポストすることで、すべてのトップレベルのウィンドウを閉じようとします。ウィンドウはイベントを無視してシャットダウン処理をキャンセルできます。

QCoreApplication::exit() を呼び出して、無条件の動作を維持します。

QLibraryInfo::location()とQLibraryInfo::Locationは、名前の一貫性がないため、非推奨となりました。代わりに新しい APIQLibraryInfo::path() とQLibraryInfo::LibraryPath を使用してください。

Qt ステートマシン フレームワーク

Qt State Machineは Qt SCXML モジュール(近々 Qt State Machines に改名予定)に移動されたため、Qt Core の一部ではなくなりました。Qt Core 内での相互依存はほとんどなかったため、最終的にこの決定に至りました。

Qt5Compat モジュールの使用

Qt5Compat モジュールを使用するには、Qt5Compatのヘッダをインクルードパスに入れてビルドし、Qt5Compatのライブラリをリンクする必要があります。qmakeを使用している場合は、.pro

QT += core5compat

cmake を使用してアプリケーションやライブラリをビルドする場合は、CMakeList.txt に以下を追加してください:

PUBLIC_LIBRARIES
    Qt::Core5Compat

本ドキュメントに含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。