2

iostreamと他のストリームクラスは実際にはクラスではなくtypedef、 s ですよね?

ここに問題がありistreamます。初期化リストでオブジェクトを初期化しようとしましたが、残念ながらエラーが発生しました。コードは次のようになります。

class A 
{
    public:
        A(istream &is=cin): ais(is)
        {}

    private:
        istream ais;
};

g++ でコンパイルできません。エラー:

synthesized method ‘std::basic_istream<char, std::char_traits<char> >::basic_istream(const std::basic_istream<char, std::char_traits<char> >&)’ first required here 

SOを検索したところ、iostream cannot be assigned or copy. しかし、なぜ初期化リストで初期化できないのでしょうか?

私が思うに、初期化リストはオブジェクトのコンストラクター/コピーコンストラクターを呼び出しますよね?

4

6 に答える 6

7

istreamコードは、コンストラクターに渡された1つをコンストラクターとに渡された2つistreamのsに変換しようとしaisます。istreamオブジェクトは、その実際のストリーム自体を表します。ストリームは1つしかなく、どういうわけかそれを2つのストリームに変える方法はありません。

それが何を意味するのかさえはっきりしていません。ストリームにデータがある場合、最初に読み取ったストリームのどちらがそれを取得しますか?それとも彼らは両方ともそれを手に入れますか?もしそうなら、誰または何がそれを複製しますか?

Anistreamはファイル自体のようなものです。自分でデータをコピーせずに、1つのファイルを2つのファイルに変換することはできません。ただし、同じものへの参照またはポインタを必要な数だけ持つことができistreamます。あなたの問題の解決策はおそらくais参照をすることです。

于 2012-01-09T08:48:39.803 に答える
5

次のように宣言されたメンバー変数があります。

istream ais;

これは、コピー コンストラクターが初期化子リストで呼び出されることを意味します。これはイニシャライザ リストに固有のものではありません。これはどこでも実行できません。

メンバー変数を参照に変更できます。

istream& ais;

istreamただし、これaisは、参照する が の存続期間中有効であることを確認する必要があることを意味しますA

于 2012-01-09T08:51:38.133 に答える
3

iostreamやその他のストリームクラスは実際にはクラスではありませんが、typedefですよね?

はい、しかしそれは関係ありません。

しかし、なぜ初期化リストで初期化できないのですか?

コピーも割り当てもできないからです。Ctorの初期化リストは魔法ではありません。aisから作成isするには、コピーを作成する必要がありますが、作成することはできません。

于 2012-01-09T08:49:38.653 に答える
2

ストリーム オブジェクトは、データ ストリームへのハンドルを表します。意味のないコピペ。また、ストリームの基本部分だけをコピーするのは適切ではありません。これは、興味深いビットを切り取ることになります (ただし、ストリーム バッファを使用して実際に興味深い部分を取得することはできます)。

ストリームを保持している場合にクラスで初期化したいものは、ストリームへの参照です。

std::istream& ais;

もちろん、これは、ストリームを使用している限り、ストリームを存続させる必要があることを意味します。これがあなたの望むものではない、または必要でない場合は、例えば をクラスに保持させ、コンストラクターの引数としてstd::ifstream受け取ることができstd::stringます。文字列が空でない場合は、対応するファイルを開きます。rdbuf()それ以外の場合は、ストリームを次のものに設定しますstd::cin

if (name.empty())
    ais.open(name.c_str());
else
    ais.rdbuf(std::cin.rdbuf());
于 2012-01-09T09:02:10.797 に答える
1

既に得た回答に加えて、渡したストリームのstreambufaisを使用して (定義どおりに)初期化することもできます (もちろん、参照と同じ警告が適用されます: streambuf が有効なままであることを確認する必要があります。オブジェクトは破棄されます)。

基になる streambuf を使用して初期化することは、おそらく実行できるストリームをコピーすることに最も近い方法です。どちらも同じファイルから読み取り、同じバッファリング (および streambuf が行う可能性のある他の処理) を使用しますが、すべての書式設定とエラー処理フラグは分離されています。

aisstreambuf で初期化するには、次のように記述します。

class A 
{
public:
  A(std::istream& is = std::cin):
    ais(is.rdbuf())
  {
  }
private:
  std::istream ais;
};
于 2012-01-09T08:59:39.020 に答える
1
class A 
{
    public:
        A(istream &is=cin): ais(is)
        {}

    private:
        istream& ais;
};

メンバーが参照型であることに注意してください。あなたが書いたように、メンバーを初期化するためにコピーを作成しています。

于 2012-01-09T09:51:29.143 に答える