c++ 範囲forとイテレータについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
カワウソ

c++ 範囲forとイテレータについて

#1

投稿記事 by カワウソ » 7年前

こんにちは。

c++の範囲forとイテレータについての質問です。
クラス内で宣言した別の自作クラスに、範囲forとイテレータを用いて代入する方法を教えてください。

○聞きたいことの詳細
以下のコードのようにコンストラクタで範囲forとイテレータを用いて代入すると、for内では代入されていますが、forを抜けると代入されていません。
ためしに従来のfor文の書式で代入してみると、うまくいきました。
そこで、聞きたいことは以下の2点です。

 1.範囲forとイテレータを用いて代入ができなかった原因
 2.このコンストラクタ内で範囲forとイテレータを用いて代入を行う場合の正しい書き方

どなたか分かる方がいればお教えください。
おそらくはアクセスの仕方が悪くて、一時的に生成されたインスタンスに代入してしまっているんじゃないかなーと思うのですが…


以下ソースコード。
----

コード:

#include <string>
#include <iostream>
#include <vector>
#include <initializer_list>

using namespace std;

class CSign
{
public:
	int id;
	string sign;
	int value;

	CSign(const char* s) : sign(s) {}
	~CSign() {}

	friend ostream& operator<<(ostream& os, const CSign& cls) {
		os << cls.sign;
		return os;
	}
};

class CFixedDo
{
public:
	vector<CSign> noteName = initializer_list<CSign>{ "C", "D", "E", "F", "G", "A", "B" };

	CFixedDo() {
		//範囲forとイテレータを用いて初期化.
		int i = 0;
		for (auto it : this->noteName) {
			it.id = i;
			it.value = i;
			//for内での代入は成功している
			//cout << it.id << "\t" << it.sign << "\t" << it.value << endl;
			++i;
		}
		show();			//ゴミが表示される
		cout << endl;

		//従来のfor文で初期化.
		for (int i = 0, n = (int)this->noteName.size(); i < n; ++i) {
			this->noteName[i].id = i;
			this->noteName[i].value = i;
		}
		show();			//代入成功
	}
	~CFixedDo() {}

	inline void show() const
	{
		for (auto it : this->noteName) cout << it.id << "\t" << it.sign << "\t" << it.value << endl;
	}
};

void main()
{
	CFixedDo nn;

	return;
}

//EOF

inemaru
記事: 108
登録日時: 7年前

Re: c++ 範囲forとイテレータについて

#2

投稿記事 by inemaru » 7年前

カワウソ さんが書きました:  1.範囲forとイテレータを用いて代入ができなかった原因
auto it は、一時変数なので、代入を行っても元の配列の内容には影響しません。
(it には、vector配列の要素がコピーされているだけ)
カワウソ さんが書きました:  2.このコンストラクタ内で範囲forとイテレータを用いて代入を行う場合の正しい書き方
auto& it に変更することで、要素への参照を取得できます。
配列要素への参照なので、元配列の書き換えが行われます。
  • 範囲ベースfor
    (抜粋)

    コード:

    // 範囲forとイテレータを用いて初期化.
    int i = 0;
    for (auto& it : this->noteName)
    {
    	it.id = i;
    	it.value = i;
    	//for内での代入は成功している
    	//cout << it.id << "\t" << it.sign << "\t" << it.value << endl;
    	++i;
    }
    
  • イテレータ
    (追記分です。)

    コード:

    int i = 0;
    for (auto it = this->noteName.begin(); it != this->noteName.end(); ++it) {
    	it->id = i;
    	it->value = i;
    	++i;
    }
    
最後に編集したユーザー inemaru on 2017年2月20日(月) 20:23 [ 編集 2 回目 ]

Rittai_3D
記事: 525
登録日時: 11年前

Re: c++ 範囲forとイテレータについて

#3

投稿記事 by Rittai_3D » 7年前

32行目が参照になっていないから代入できていないのではないでしょうか。
実行結果
► スポイラーを表示
range-based forは

コード:

auto begin = std::begin( v );
auto end = std::end( v );

for( ; begin != end ; ++begin ) {
    auto it = *begin;
}
のように展開され、itはコピーになるので、元のnoteNameには影響を与えません。
初心者です

カワウソ

Re: c++ 範囲forとイテレータについて

#4

投稿記事 by カワウソ » 7年前

お二人とも、すばやい返信をありがとうございます。

そうですね。参照を忘れていました。
なんで気づかなかったんだろう(笑)

解決しました。ありがとうございます。

閉鎖

“C言語何でも質問掲示板” へ戻る