• 締切済み

メンバ変数が変更されそうなconstメンバ関数

c++のconstメンバ関数についての質問です。 以下のコードの様に、constメンバ関数で メンバ変数を変更しているように見える場合、 本来はどのように記述すべきか? class foo { public: foo(){} foo(int i){ d = i; } void hoge(foo *dest0, foo *dest1 ) const { dest0->d = d*2; dest1->d = d*4; } int d; }; int main() { foo f(1); foo p,q; f.hoge(&p,&q); std::cout << f.d << "\n"; std::cout << p.d << "\n"; std::cout << q.d << "\n"; f.hoge(&f,&q); std::cout << f.d << "\n"; std::cout << q.d << "\n"; return 0; } ちなみに出力期待値は 1 2 4 2 4 とします。 上のコードは 1 2 3 2 8 と出力されますが、このようなことが無いように実装するには どうすべきかという質問です。 dest0->d = d*2; dest1->d = d*4; の所を int i=d; dest0->d = i*2; dest1->d = i*4; とすべき? それともhogeの最初に if( (this == dest0) || (this == dest1) || (dest0== dest1) ){ throw "同じオブジェクトじゃだめ"; } とすべき? どんな書き方が安定でしょうか?

みんなの回答

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「意味からいって同じオブジェクトを指定できるかどうか」がまず問題で, 「同じオブジェクトを指定する意味がある」なら前者, 「無意味である」あるいは「してはならない」なら後者の形になるんでは? もっとも, このようなメンバー関数を作らなければならないとしたら「設計が間違っている」ような気もするんだけど....

ICE_FALCON
質問者

お礼

回答ありがとうございます。 > 「同じオブジェクトを指定する意味がある」なら前者, 「無意味である」あるいは「してはならない」なら後者の形になるんでは? やはり場合によりけりですか。 > 「設計が間違っている」ような気もするんだけど.... うーん、2つ以上同時に戻したい場合はこうなるような気がしますが・・・・。

関連するQ&A

  • const参照メンバを含む要素のvector

    久しぶりに趣味でプログラミングしてます。 const参照のメンバを含むオブジェクトを要素に持つvector って使えます? 下記はbcc32でコンパイルするとエラーが出ます。 _algobase.h 145:コンパイラは 'operator=' クラスの hoge を作成できない(関数 _STL::hoge * __copy<hoge *,hoge *,int>(hoge *,hoge *,hoge *,const random_access_iterator_tag &,int *) ) ちなみにv.clear();をコメントアウトするとコンパイルは通り実行も問題なくできます。 clear()の替わりにpop_back()としてもコンパイルは通り実行も問題なくできます。 コンパイラーのバグ?そもそもこんなことをしてはダメ? よろしくお願いします。 class hoge { public:  hoge(const int &i):_i(i){};  virtual ~hoge(){};  operator int () const {return _i;}  const int &_i; }; int main() {  int i1=1;  int i2=2;  hoge h1(i1);  hoge h2(i2);  std::vector<hoge > v;  v.push_back(h1);  v.push_back(h2);  v.clear();  std::vector<hoge >::iterator iter = v.begin();  while( iter != v.end() ){   std::cout << *iter << "\n";   ++iter;  }  return 0; }

  • static constメンバ変数(配列)の初期化について

    C++初心者です。 constメンバ変数の初期化について教えてください。 クラスの中に、static constメンバ変数(配列)を持ちたいのですが、 <コード1> class hoge { public : hoge(){}; virtual ~hoge(){}; static const int fuga[2] = {1, 2}; }; とすると、VC++ 2005では、 error C2059: 構文エラー : '{' error C2334: '{' の前に予期しないトークンがありました。関数の本体は無視されます というエラーが発生します。 何がいけないのでしょうか? また、下の様にするとOKでした。 <コード2> class hoge { public : hoge(){}; virtual ~hoge(){}; static const int fuga[2]; }; const int hoge::fuga[2] = {1,2}; こうすればコンパイルが通る事は分かったのですが、なぜこんな面倒な事をしないといけないのかが分かりません。 コード1では何がいけないのでしょうか? 以上、よろしくお願いします。

  • constのついたメンバ関数

     こんにちは。 C++を勉強しているのですが疑問に思ったことがあります。 const指定したメンバ関数にメンバ変数の変更をすることはエラーになるはずなんですが、 下記にある(*m_pRefCnt)++; はコンパイルが通るようです。 なぜこの一文だけ通るのでしょうか? 以下にソースを添付しておきます。 #include <iostream> class hogeClass { private: int* m_pRefCnt; int val; void AddRef() const { (*m_pRefCnt)++; // これはOK? val = 100; // これは駄目 } void Release() { } public: explicit hogeClass(char* src = NULL) : val(0) { } int& GetRefCnt() { return *(m_pRefCnt); } virtual ~hogeClass() { Release(); } }; int main() { int c = 435, k = 222; using namespace std; hogeClass a; getchar(); return 0; } 分かる人がいたらよろしくお願いします。

  • C++ iteator const を使ったプログラムがコンパイルできない

    以下のプログラムがコンパイルできません。 理由もよく分かりません。 ----------------- #include <algorithm> #include <list> struct Hoge { std::list<Hoge*> l; Hoge * f() const { std::list<Hoge*>::iterator i = l.begin(); return 0; } }; -------------------- g++ 4.1.1 を使っていますが % g++ -c test1.cc test1.cc: In member function 'Hoge* Hoge::f() const': test1.cc:8: error: conversion from 'std::_List_const_iterator<Hoge*>' to non-scalar type 'std::_List_iterator<Hoge*>' requested となります。 l.begin() が const で代入できないということだと思うのですが std::list<Hoge*> l; の部分には const を使っていませんし良く分かりません。 また、 Hoge * eval() const { の const を消すか、 std::list<Hoge*>::iterator i = l.begin(); の代入をやめると コンパイルが通ります。 const は return するポインタの先の領域を変更不可にしている と解釈しているのですが、戻り値と関係ない代入がどうして影響を受けるのかが謎です。 (実際は、もう少し違う大きいプログラムですが関係なさそうな部分を削って 上でも同様のエラーメッセージが出ることを確認しました。)

  • クラスのメンバ変数のnew

    こんにちは。 クラスのメンバ変数の動的割り当てで困っていることがあります。 コンストラクタ内でメンバ変数に動的割り当てをするんですが、そこで例外処理をしなければならないようです。 例 class foo::foo() { try{ hoge = new int[100]; // hogeの代入処理 // } catch { delete[] hoge; hoge = NULL; } } foo::~foo() { delete[] hoge; hoge = NULL; } しかしこれだと不十分なようで、なかしかの対策をしないとメモリリークが起きてしまいそうなんですが どのようにやるんでしょうか?

  • (C++)スマートポインタをメンバ変数で使いたい

    Viual Studio 2013を使ってC++のコードを書いています。 以下のコードで、new-deleteの クラス生成をスマートポインタで置き換えたいのですが、 うまくいきません。具体的には/* not smart */の部分を スマートポインタで置き換えたいが、C2059のエラーが出てきて コンパイルできないのが理解できていません。 どなたかわかる方教えていただければ幸いです。 よろしくお願いします。 // ----コードは以下---- #include <memory> #include <iostream> class Hoge { public: Hoge(){ std::cout << "constructed!" << std::endl; }; ~Hoge(){ std::cout << "destructed!" << std::endl; }; private: }; class Hogehoge { public: Hogehoge(){}; ~Hogehoge(){ delete test; /* not smart */}; private: // error C2059 w/ VS2013 // std::unique_ptr<Hoge> test(new Hoge); Hoge* test = new Hoge; /* not smart */ }; void main() { Hogehoge foo; }

  • 添字演算子

    #include <iostream> class hoge{ private: int a; public: hoge(){ a = 0; } int operator+(int fuga){ a = a + fuga; return a; } int operator[](int fuga){ return 1; } }; int main(){ hoge* p; p = new hoge; std::cout << ((*p) + 5) << std::endl; std::cout << ((*p)[1] ) << std::endl; // 5 // 1 // std::cout << ((*p) [] 1); エラーです。何故ですか? }

  • constについて

    #include <iostream> using namespace std; class I { int *x; public: unsigned int size; I(){size=0;x=new int[size];} I(unsigned int i){size=i;x=new int[size];} ~I(){delete []x;} int &operator()(unsigned int i){return x[i];}//!!!! const int &operator()(unsigned int i) const{return x[i];}//???? }; void main() { I a(10); for(int i=0;i<10;i++)a(i)=i;a(2)=a(0); for(int i=0;i<10;i++)cout<<a(i); } この場合は//????はいらないと思いますが //????を定義することがありますがどんな場合でしょう //!!!!があるのにあったほうがいいのはどんな場合でしょう?

  • 参照について

    C++初心者です。 #include <iostream> using namespace std; class Foo{ public: Foo() {;} Foo(const Foo&) {cout<< "A ";} Foo& operator = (const Foo&){cout << "B "; return *this;}   ←← }; int main(){ Foo x; x = Foo(); return 0; } において←←の部分を上記のようにFoo& operatorにした場合には 出力が"B"となりFoo operatorにした場合には出力が"B A"になりました。&がある場合と無い場合でどのようなことが起こっているのかよく分からないのですが教えて頂けないでしょうか? よろしくお願いします。

  • 警告「代入される前に使われている」を出す方法

    bccで以下のコードをコンパイルすると。 「'i' は、おそらく値が代入される前に使われている」 と警告が出ますが、 「'h' は、おそらく値が代入される前に使われている」 とは警告を出してくれません。 警告を出す方法ってないでしょうか? Hogeメンバに bool 型の初期化フラグでも実装しようかな・・・。 #include <iostream> class Hoge { public: Hoge(){ } Hoge( int i ){ t = i; } operator int(){ return t; } int t; }; int main() { int i; Hoge h; std::cout << i << std::endl; std::cout << h << std::endl; return 0; }

専門家に質問してみよう