ページ 11

参照とポインタ

Posted: 2009年5月19日(火) 16:38
by 大工
引数の定義の仕方で良く分からない仕様だったので質問させてください

参照で関数funcを定義した場合,

_vec.retest()

と定義出来ますが,

ポインタで定義した場合,

_vec.retest()
_vec->retest()

2パターンで書いてもエラーが出ました.

'->'のパターン
$ g++ -o test test.cpp
test.cpp: In function ‘void func(std::vector<TEST, std::allocator<TEST> >*)’:
test.cpp:33: error: base operand of ‘->’ has non-pointer type ‘std::vector<TEST, std::allocator<TEST> >’

'.'のパターン
$ g++ -o test test.cpp
test.cpp: In function ‘void func(std::vector<TEST, std::allocator<TEST> >*)’:
test.cpp:33: error: ‘class std::vector<TEST, std::allocator<TEST> >’ has no member named ‘retest’

呼び方に大きな違いがあるとは思うのですが,参照とポインタの違いを良く分かっていないのが現状です.
詳しい方,よろしくお願いします.

*参照*
#include<iostream>
#include<vector>

class TEST {

private:
  int test;

public:
  TEST(int i) : test(i * 10) {}
  int retest() {return test;}

};

void func(std::vector<TEST>&);

int main(void) {

  std::vector<TEST> vec;

  for(int i = 0; i < 10; i++) vec.push_back(TEST(i));

  std::cout << "main" << std::endl;
  for(int i = 0; i < 10; i++) std::cout << vec.retest() << std::endl;

  func(vec);

  return 0;
}

void func(std::vector<TEST>& _vec) {

  for(int i = 0; i < 10; i++) std::cout << _vec.retest() << std::endl;

}


*ポインタ*

#include<iostream>
#include<vector>

class TEST {

private:
  int test;

public:
  TEST(int i) : test(i * 10) {}
  int retest() {return test;}

};

void func(std::vector<TEST>*);

int main(void) {

  std::vector<TEST> vec;

  for(int i = 0; i < 10; i++) vec.push_back(TEST(i));

  std::cout << "main" << std::endl;
  for(int i = 0; i < 10; i++) std::cout << vec.retest() << std::endl;

  func(&vec);

  return 0;
}

void func(std::vector<TEST>* _vec) {

  for(int i = 0; i < 10; i++) std::cout << _vec.retest() << std::endl;

}

Re:参照とポインタ

Posted: 2009年5月19日(火) 16:52
by Blue
>_vec.retest()
(*_vec).retest();
では?

Re:参照とポインタ

Posted: 2009年5月19日(火) 16:54
by 大工
あ,あれ・・・通りました・・・

なんで・・・

Re:参照とポインタ

Posted: 2009年5月19日(火) 17:03
by Blue
ポインタなんだからoperator [/url] がないわけで、
実態にしてoperator [/url] を呼ぶようにする。

atメソッドでもoperator [/url] と同じことができるので書き換えると
std::vector<std::string> v;
v.push_back("hoge");

//std::cout << v[0].c_str() << std::endl;
std::cout << v.at(0).c_str() << std::endl;

std::vector<std::string>* p = &v;

//std::cout << (*v)[0].c_str() << std::endl;
std::cout << p->at(0).c_str() << std::endl;
という感じ。

Re:参照とポインタ

Posted: 2009年5月19日(火) 17:13
by Blue
ちなみにこんなのもできる。
//std::cout << v[0].c_str() << std::endl;
std::cout << v.operator [/url](0).c_str() << std::endl;

//std::cout << (*v)[0].c_str() << std::endl;
std::cout << p->operator [/url](0).c_str() << std::endl;

Re:参照とポインタ

Posted: 2009年5月19日(火) 19:31
by 大工
ふむふむ...

[/url]このオペーレーターだけで実体化してるものだと思っていました....

ありがとうございました.

Re:参照とポインタ

Posted: 2009年5月19日(火) 19:55
by たかぎ
> ポインタなんだからoperator [/url] がないわけで、

いや、ポインタに対して添え字演算子を使うと、組み込みの[/url]とみなされてしまいます。

つまり、_vecとすると、*(_vec + i)の扱いになります。
結果として、式そのものはstd::vector<TEST>型の左辺値に評価されるわけですが、まったく的外れのアドレスの存在しないオブジェクトを触ってしまいます。

Re:参照とポインタ

Posted: 2009年5月19日(火) 23:40
by Blue
>いや、ポインタに対して添え字演算子を使うと、組み込みの[/url]とみなされてしまいます。
ですね。

std::vector<TEST>のoperator[/url]ではなくなる

としておくべきでした。