31

std::basic_stringC ++ 03では、技術的にはテンプレートに連続したメモリが必要ないことを知っています。ただし、この自由を実際に利用する最新のコンパイラーには、いくつの実装が存在するのか興味があります。たとえば、basic_stringC APIの結果を受け取るために使用したい場合(以下の例のように)、すぐに文字列に変換するためだけにベクトルを割り当てるのはばかげているようです。

例:

DWORD valueLength = 0;
DWORD type;
LONG errorCheck = RegQueryValueExW(
        hWin32,
        value.c_str(),
        NULL,
        &type,
        NULL,
        &valueLength);

if (errorCheck != ERROR_SUCCESS)
    WindowsApiException::Throw(errorCheck);
else if (valueLength == 0)
    return std::wstring();

std::wstring buffer;
do
{
    buffer.resize(valueLength/sizeof(wchar_t));
    errorCheck = RegQueryValueExW(
            hWin32,
            value.c_str(),
            NULL,
            &type,
            &buffer[0],
            &valueLength);
} while (errorCheck == ERROR_MORE_DATA);

if (errorCheck != ERROR_SUCCESS)
    WindowsApiException::Throw(errorCheck);

return buffer;

このようなコードは、隣接していることを意味するため、移植性がわずかに低下する可能性があることを私は知っstd::wstringていますが、このコードがどれほど移植性が低いのか疑問に思っています。言い換えれば、コンパイラは、非連続メモリが許す自由を実際にどのように利用できるでしょうか。


編集:C++03に言及するためにこの質問を更新しました。basic_string読者は、C ++ 11を対象とする場合、標準では連続している必要があることに注意する必要があります。したがって、その標準を対象とする場合、上記の質問は問題になりません。

4

5 に答える 5

25

std::stringがストレージを連続して割り当てると仮定するのは非常に安全だと思います。

現時点では、既知のすべての実装でstd::stringスペースを連続して割り当てています。

さらに、C ++ 0x(N3000)の現在のドラフト[編集:警告、大きなPDFへの直接リンク]では、スペースを連続して割り当てる必要があります(§21.4.1/ 5)。

basic_stringオブジェクトのcharのようなオブジェクトは、連続して格納されます。つまり、basic_stringオブジェクトsの場合、アイデンティティ&*(s.begin()+ n)==&* s.begin()+ nは、0 <=n<s.sizeとなるnのすべての値に対して保持されます。 ()。

std::stringそのため、非連続ストレージを使用する現在または将来の実装の可能性は基本的にゼロです。

于 2010-02-13T02:08:34.920 に答える
14

しばらく前に、aのストレージstd::stringに文字の配列であるかのように書き込むことができるかどうかについての質問があり、それはaの内容std::stringが連続しているかどうかにかかっていました。

私の答えは、いくつかの評判の良い情報源( HerbSutterとMattAustern)によると、現在のC ++標準では、std::string特定の条件下でデータを連続して保存する必要があることを示しています。任意の実装。str[0]strstd::string

基本的に、によって行われた約束を組み合わせて、それが連続したバッファを返す必要があるstring::data()string::operator[]()結論付けた場合。&str[0]したがって、Austernは、委員会がそれを明示的にすることを提案し、明らかにそれが0x標準で起こることです(または彼らは今それを1x標準と呼んでいますか?)。

std::stringしたがって、厳密に言えば、実装は連続したストレージを使用して実装する必要はありませんが、ほとんどオンデマンドで実装する必要があります。そして、サンプルコードは、を渡すことでそれを実行し&buffer[0]ます。

リンク:

于 2010-02-13T04:54:36.390 に答える
0

編集:非参照を返し、その内容が予期せず変更される可能性があることをオブジェクトに通知するため&buffer[0]、ではなく buffer.data()、を呼び出します。[]const


実行する方がクリーンですがbuffer.data()、構造間で共有されるメモリよりも、連続するメモリについて心配する必要はありません。string実装は、オブジェクトが変更されているときに通知されることを期待できます。string::data特に、プログラムが返された内部バッファを変更しないことを要求します。

一部の実装では、長さが10などに設定されている以外に、初期化されていないすべての文字列に対して1つのバッファが作成される可能性が非常に高くなります。

/を使用して、vectorまたは配列を使用します。本当にバッファをコピーできない場合は、文字列を変更する前に、文字列を一意の文字列に合法的に初期化してください。new[]delete[]

于 2010-02-13T07:37:06.450 に答える
-1

結果は未定義であり、私はそれをしません。最近のC++ヒープでは、ベクトルを読み取ってから文字列に変換するコストはわずかです。VSあなたのコードがWindows9で死ぬリスク

また、&buffer [0]にconst_castが必要ではありませんか?

于 2010-02-13T02:01:06.077 に答える
-2

もちろん、ここでベクトルを割り当てるのはばかげています。ここでstd::wstringを使用することも賢明ではありません。winapiを呼び出すにはchar配列を使用することをお勧めします。値を返すときにwstringを作成します。

于 2010-02-13T02:07:44.273 に答える