1. ホーム
  2. c++

std::stringをバッファとして使用することのデメリットはありますか?

2023-12-21 02:32:28

質問

最近、私の同僚が std::string をバッファとして使っているのを見ました。

std::string receive_data(const Receiver& receiver) {
  std::string buff;
  int size = receiver.size();
  if (size > 0) {
    buff.resize(size);
    const char* dst_ptr = buff.data();
    const char* src_ptr = receiver.data();
    memcpy((char*) dst_ptr, src_ptr, size);
  }
  return buff;
}

この人は、返された文字列の自動破壊を利用したいのでしょう。そうすれば、割り当てられたバッファの解放を心配する必要がありません。

これはちょっと 奇妙な によると cplusplus.com data() メソッドは const char* は文字列が内部で管理するバッファを指します。

const char* data() const noexcept;

const char ポインタへの Memcpy-ing ? AFAIKは、私たちが何をするか知っている限り、これは害を及ぼさないが、私は何かを見逃していますか?これは危険ですか?

どのように解決するのですか?

を使用しないでください。 std::string をバッファとして使用しないでください。

を使用するのはバッドプラクティスです。 std::string をバッファとして使用するのは、いくつかの理由(順不同)があります。

  • std::string はバッファとしての使用を意図したものではありません。クラスの説明を再確認して、特定の使用パターンを妨げる (または未定義の動作を引き起こす) ような "gotchas" がないことを確認する必要があります。
  • 具体的な例として。C++17 以前、あなたは を書くことさえできません。 で得られるポインタを通して data() - で得られるポインタを介して const Tchar * であるため、あなたのコードは未定義の動作を引き起こすでしょう。(しかし &(str[0]) , &(str.front()) または &(*(str.begin())) が使えるでしょう)。
  • 使用する std::string をバッファに使うのは、関数の定義を読む人を混乱させます。 std::string を使っているのだろうと考えるからです。言い換えれば、そうすることで 最小驚嘆の原則 .
  • さらに悪いことに、次のような人は混乱することになります。 を使う 彼らは、あなたが返しているものが文字列、すなわち人間が読める有効なテキストであると考えるかもしれません。
  • std::unique_ptr は、あなたのケースに適していますし、あるいは std::vector . C++17では std::byte を要素の型に使用することもできます。より洗練されたオプションとして、クラスで SSO -のような機能、例えば Boost の small_vector のようなものです (言及してくれた @gast128 さん、ありがとうございます)。
  • (細かい点ですが) libstdc++ は、その ABI を std::string の ABI を C++11 標準に準拠するように変更したため、場合によっては (今ではほとんどないでしょうが)、リンクや実行時に 問題 が発生する可能性があります。

また、あなたのコードはヒープ割り当てを1回ではなく2回行うかもしれません(実装に依存します)。文字列の構築時に一度、そして resize() のときです。しかし、それ自体が std::string の構造を使って二重の割り当てを避けることができるからです。 Jarod42 さんの回答 .