| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

「C++ ポインタ」の版間の差分

提供: MyMemoWiki
ナビゲーションに移動 検索に移動
(ページの作成:「==C++ ポインタ== [C++][C++によるオブジェクト指向プログラミング] {{amazon|4756118895}} ===ポインタ型=== *ポインタは、変数および…」)
 
 
(同じ利用者による、間の3版が非表示)
1行目: 1行目:
 
==C++ ポインタ==
 
==C++ ポインタ==
[C++][C++によるオブジェクト指向プログラミング]
+
[[C++]] | [[C++によるオブジェクト指向プログラミング]] |
 
{{amazon|4756118895}}
 
{{amazon|4756118895}}
  
13行目: 13行目:
  
 
=====例=====
 
=====例=====
  #include <iostream>
+
  #include &lt;iostream&gt;
 
   
 
   
 
  using namespace std;
 
  using namespace std;
22行目: 22行目:
 
     int* p = &i;  // ポインタを i のアドレスに初期化
 
     int* p = &i;  // ポインタを i のアドレスに初期化
 
   
 
   
     cout << *p << endl;  // ポインタが指す変数の値を出力
+
     cout &lt;&lt; *p &lt;&lt; endl;  // ポインタが指す変数の値を出力
 
   
 
   
 
     int j = *p + 1;      // ポインタが指す変数の値に +1 した値でjを初期化
 
     int j = *p + 1;      // ポインタが指す変数の値に +1 した値でjを初期化
 
   
 
   
     cout << j << endl;
+
     cout &lt;&lt; j &lt;&lt; endl;
 
   
 
   
 
     p = &j;              // j のアドレスをポインタに設定  
 
     p = &j;              // j のアドレスをポインタに設定  
 
   
 
   
     cout << *p << endl;  // p は j を指す
+
     cout &lt;&lt; *p &lt;&lt; endl;  // p は j を指す
 
   }
 
   }
  
 
=====結果=====
 
=====結果=====
  W:\oop02\Debug>oop02.exe
+
  W:\oop02\Debug&gt;oop02.exe
 
  5
 
  5
 
  6
 
  6
43行目: 43行目:
 
#関数呼び出し時に、引数としてアドレスを渡す
 
#関数呼び出し時に、引数としてアドレスを渡す
 
=====例=====
 
=====例=====
  #include <iostream>
+
  #include &lt;iostream&gt;
 
   
 
   
 
  using namespace std;
 
  using namespace std;
62行目: 62行目:
 
     int len = sizeof(nums) / sizeof(nums[0]);
 
     int len = sizeof(nums) / sizeof(nums[0]);
 
   
 
   
     for (int i=0; i<len; i++) {
+
     for (int i=0; i&lt;len; i++) {
         for (int j=i; j<len; j++) {
+
         for (int j=i; j&lt;len; j++) {
 
             // 引数としてアドレスを渡す
 
             // 引数としてアドレスを渡す
 
             order(&nums[i], &nums[j]);         
 
             order(&nums[i], &nums[j]);         
 
         }
 
         }
 
     }
 
     }
     for (int i=0; i<len; i++) {
+
     for (int i=0; i&lt;len; i++) {
         cout << nums[i] << endl;
+
         cout &lt;&lt; nums[i] &lt;&lt; endl;
 
     }
 
     }
 
  }
 
  }
77行目: 77行目:
 
     int tmp;
 
     int tmp;
 
     // ポインタを間接参照する
 
     // ポインタを間接参照する
     if (*n > *m) {
+
     if (*n &gt; *m) {
 
         tmp = *n;
 
         tmp = *n;
 
         *n  = *m;
 
         *n  = *m;
84行目: 84行目:
 
  }
 
  }
 
=====結果=====
 
=====結果=====
  W:\oop02\Debug>oop02.exe
+
  W:\oop02\Debug&gt;oop02.exe
 
  2
 
  2
 
  3
 
  3
115行目: 115行目:
 
  ip = &i;
 
  ip = &i;
 
  cp = &c;
 
  cp = &c;
  cout << *ip << "," << *cp << endl;
+
  cout &lt;&lt; *ip &lt;&lt; "," &lt;&lt; *cp &lt;&lt; endl;
 
   
 
   
 
  vp = &i;                                // intポインタを 汎用ポインタに変換
 
  vp = &i;                                // intポインタを 汎用ポインタに変換
  int j = *reinterpret_cast<int*>(vp);    // 汎用ポインタを intポインタに変換
+
  int j = *reinterpret_cast&lt;int*&gt;(vp);    // 汎用ポインタを intポインタに変換
  cout << j << endl;
+
  cout &lt;&lt; j &lt;&lt; endl;
 
   
 
   
 
  vp = &c;                                // charポインタを 汎用ポインタに変換
 
  vp = &c;                                // charポインタを 汎用ポインタに変換
  char d = *reinterpret_cast<char*>(vp);  // 汎用ポインタを charポインタに変換
+
  char d = *reinterpret_cast&lt;char*&gt;(vp);  // 汎用ポインタを charポインタに変換
  cout << d << endl;
+
  cout &lt;&lt; d &lt;&lt; endl;
 
   
 
   
 
  // error C2100: 間接指定演算子 (*) の使い方が正しくありません。
 
  // error C2100: 間接指定演算子 (*) の使い方が正しくありません。
  // cout << *vp << endl;                // 汎用ポインタの間接参照不可
+
  // cout &lt;&lt; *vp &lt;&lt; endl;                // 汎用ポインタの間接参照不可
 
   
 
   
 
  // 'char *' から 'int *' に変換できません。
 
  // 'char *' から 'int *' に変換できません。
145行目: 145行目:
 
   
 
   
 
  // 連続したアドレスを確保
 
  // 連続したアドレスを確保
  for (int i=0; i<SIZE; i++) {
+
  for (int i=0; i&lt;SIZE; i++) {
     cout << &nums[i] << ",";
+
     cout &lt;&lt; &nums[i] &lt;&lt; ",";
 
  }
 
  }
  cout << endl;
+
  cout &lt;&lt; endl;
 
   
 
   
 
  // 配列のベースアドレスは先頭アドレス
 
  // 配列のベースアドレスは先頭アドレス
  cout << &nums << endl;
+
  cout &lt;&lt; &nums &lt;&lt; endl;
 
   
 
   
 
  // nums + 1 と &nums「1] は等しい
 
  // nums + 1 と &nums「1] は等しい
 
  int* ip = nums + 1;
 
  int* ip = nums + 1;
  cout << ip << "=" << *ip << endl;
+
  cout &lt;&lt; ip &lt;&lt; "=" &lt;&lt; *ip &lt;&lt; endl;
 
  int* ip2 = &nums[1];
 
  int* ip2 = &nums[1];
  cout << ip2 << "=" << *ip2 << endl;
+
  cout &lt;&lt; ip2 &lt;&lt; "=" &lt;&lt; *ip2 &lt;&lt; endl;
  
 
=====結果=====
 
=====結果=====
174行目: 174行目:
 
  int&  ri  = i;        // i の参照
 
  int&  ri  = i;        // i の参照
 
   
 
   
  cout << i << "," << *pi << "," << ri << endl;
+
  cout &lt;&lt; i &lt;&lt; "," &lt;&lt; *pi &lt;&lt; "," &lt;&lt; ri &lt;&lt; endl;
  cout << "&i=" << &i << ", &pi=" << &pi << ", &ri=" << &ri << endl;
+
  cout &lt;&lt; "&i=" &lt;&lt; &i &lt;&lt; ", &pi=" &lt;&lt; &pi &lt;&lt; ", &ri=" &lt;&lt; &ri &lt;&lt; endl;
 
   
 
   
 
  *pi = 9;
 
  *pi = 9;
  cout << i << "," << *pi << "," << ri << endl;
+
  cout &lt;&lt; i &lt;&lt; "," &lt;&lt; *pi &lt;&lt; "," &lt;&lt; ri &lt;&lt; endl;
 
   
 
   
 
  i = 10;
 
  i = 10;
  cout << i << "," << *pi << "," << ri << endl;
+
  cout &lt;&lt; i &lt;&lt; "," &lt;&lt; *pi &lt;&lt; "," &lt;&lt; ri &lt;&lt; endl;
 
   
 
   
 
  // 一旦宣言されると、別のオブジェクトの参照にはなれない
 
  // 一旦宣言されると、別のオブジェクトの参照にはなれない
 
  int j = 11;
 
  int j = 11;
 
  ri = j;
 
  ri = j;
  cout << i << "," << *pi << "," << ri << endl;
+
  cout &lt;&lt; i &lt;&lt; "," &lt;&lt; *pi &lt;&lt; "," &lt;&lt; ri &lt;&lt; endl;
 
   
 
   
 
  // ポインタはアドレスを記憶した変数だが、参照はエイリアスであり同じオブジェクトを指す
 
  // ポインタはアドレスを記憶した変数だが、参照はエイリアスであり同じオブジェクトを指す
  cout << "&i=" << &i << ", &pi=" << &pi << ", &ri=" << &ri << ", &j=" << &j << endl;
+
  cout &lt;&lt; "&i=" &lt;&lt; &i &lt;&lt; ", &pi=" &lt;&lt; &pi &lt;&lt; ", &ri=" &lt;&lt; &ri &lt;&lt; ", &j=" &lt;&lt; &j &lt;&lt; endl;
  
 
=====結果=====
 
=====結果=====
209行目: 209行目:
 
     int len = sizeof(nums) / sizeof(nums[0]);
 
     int len = sizeof(nums) / sizeof(nums[0]);
 
   
 
   
     for (int i=0; i<len; i++) {
+
     for (int i=0; i&lt;len; i++) {
         for (int j=i; j<len; j++) {
+
         for (int j=i; j&lt;len; j++) {
 
             // 引数として値自身(参照)を渡す
 
             // 引数として値自身(参照)を渡す
 
             ref_order(nums[i], nums[j]);         
 
             ref_order(nums[i], nums[j]);         
 
         }
 
         }
 
     }
 
     }
     for (int i=0; i<len; i++) {
+
     for (int i=0; i&lt;len; i++) {
         cout << nums[i] << endl;
+
         cout &lt;&lt; nums[i] &lt;&lt; endl;
 
     }
 
     }
 
  }
 
  }
224行目: 224行目:
 
     int tmp;
 
     int tmp;
 
     // ポインタを間接参照する必要はない
 
     // ポインタを間接参照する必要はない
     if (n > m) {
+
     if (n &gt; m) {
 
         tmp = n;
 
         tmp = n;
 
         n  = m;
 
         n  = m;

2020年2月15日 (土) 08:34時点における最新版

C++ ポインタ

C++ | C++によるオブジェクト指向プログラミング |

ポインタ型

  • ポインタは、変数およびマシンアドレスを参照するのに使用
  • 配列および文字列の処理に緊密に結びついている
  • C++の配列は、連続したメモリに関連付けれられたインデックス付け可能な特殊なポインタ
int* p;
  • 上記は、pをintへのポインタ型として宣言している
#include <iostream>

using namespace std;

int main() 
{
    int     i  = 5;
    int* p = &i;  // ポインタを i のアドレスに初期化

    cout << *p << endl;  // ポインタが指す変数の値を出力

    int j = *p + 1;      // ポインタが指す変数の値に +1 した値でjを初期化

    cout << j << endl;

    p = &j;              // j のアドレスをポインタに設定 

    cout << *p << endl;  // p は j を指す
 }
結果
W:\oop02\Debug>oop02.exe
5
6
6

ポインタベースの参照渡し

  1. 関数ヘッダでポインタパラメータを宣言
  2. 関数本体でポインタを間接参照
  3. 関数呼び出し時に、引数としてアドレスを渡す
#include <iostream>

using namespace std;

void sort();

// ポインタパラメータを宣言
void order(int*, int*);

int main() 
{
    sort();
}

void sort() 
{
    int nums[] = { 2, 34, 656, 767, 893, 123, 5, 7, 892, 4, 6, 81, 1134, 56, 3 };
    int len = sizeof(nums) / sizeof(nums[0]);

    for (int i=0; i<len; i++) {
        for (int j=i; j<len; j++) {
            // 引数としてアドレスを渡す
            order(&nums[i], &nums[j]);        
        }
    }
    for (int i=0; i<len; i++) {
        cout << nums[i] << endl;
    }
}
 
void order(int* n, int* m)
{
    int tmp;
    // ポインタを間接参照する
    if (*n > *m) {
        tmp = *n;
        *n  = *m;
        *m  = tmp;
    } 
}
結果
W:\oop02\Debug>oop02.exe
2
3
4
5
6
7
34
56
81
123
656
767
892
893
1134

汎用ポインタ

  • void* gp のような汎用ポインタへは任意の型のアドレスを代入できる
  • 間接参照はできない
void* vp;        // 汎用ポインタ
int*  ip;        // int ポインタ
char* cp;        // char ポインタ

int  i = 10;
char c = 'a';

// それぞれの型のポインタに値を設定
ip = &i;
cp = &c;
cout << *ip << "," << *cp << endl;

vp = &i;                                // intポインタを 汎用ポインタに変換
int j = *reinterpret_cast<int*>(vp);    // 汎用ポインタを intポインタに変換
cout << j << endl;

vp = &c;                                // charポインタを 汎用ポインタに変換
char d = *reinterpret_cast<char*>(vp);  // 汎用ポインタを charポインタに変換
cout << d << endl;

// error C2100: 間接指定演算子 (*) の使い方が正しくありません。
// cout << *vp << endl;                 // 汎用ポインタの間接参照不可

// 'char *' から 'int *' に変換できません。
// ip = cp;                                // 異なる型のポインタへの変換不可
結果
10,a
10
a

配列とポインタ

  • 配列の名前それ自身ではアドレス(ポインタ値)である
  • 配列は定数ポインタとみなすことのできる特定の固定アドレス
  • 配列が宣言されるとコンパイラはすべての要素を記憶するのにたる記憶領域を割り当てる
  • 配列のベースアドレスはメモリの先頭位置でインデックス0のアドレスと等しい
const int SIZE = 5;
int nums[SIZE] = {1,2,3,4,5};

// 連続したアドレスを確保
for (int i=0; i<SIZE; i++) {
    cout << &nums[i] << ",";
}
cout << endl;

// 配列のベースアドレスは先頭アドレス
cout << &nums << endl;

// nums + 1 と &nums「1] は等しい
int* ip = nums + 1;
cout << ip << "=" << *ip << endl;
int* ip2 = &nums[1];
cout << ip2 << "=" << *ip2 << endl;
結果
0022FDDC,0022FDE0,0022FDE4,0022FDE8,0022FDEC,
0022FDDC
0022FDE0=2
0022FDE0=2

参照

  • 参照宣言は、オブジェクトの別名(エイリアス)と宣言し、簡単な形式での参照私を可能にする
  • 以下の例で、i および ri はお互いのエイリアスで同じオブジェクトを指す
  • 宣言された時点でそれに関連付けられたアドレスと記憶領域を持ち、後からは変更できない
int   i      = 5;
int*  pi  = &i;        // i のポインタ
int&  ri  = i;        // i の参照

cout << i << "," << *pi << "," << ri << endl;
cout << "&i=" << &i << ", &pi=" << &pi << ", &ri=" << &ri << endl;

*pi = 9;
cout << i << "," << *pi << "," << ri << endl;

i = 10;
cout << i << "," << *pi << "," << ri << endl;

// 一旦宣言されると、別のオブジェクトの参照にはなれない
int j = 11;
ri = j;
cout << i << "," << *pi << "," << ri << endl;

// ポインタはアドレスを記憶した変数だが、参照はエイリアスであり同じオブジェクトを指す
cout << "&i=" << &i << ", &pi=" << &pi << ", &ri=" << &ri << ", &j=" << &j << endl;
結果
5,5,5
&i=002AFDFC, &pi=002AFDF0, &ri=002AFDFC
9,9,9
10,10,10
11,11,11
&i=002AFDFC, &pi=002AFDF0, &ri=002AFDFC, &j=002AFDD8

参照渡し

  • 上の例で行った「ポインタベースの参照渡し」を参照渡しに書き換える
  • ポインタベースの参照渡しでは、ポインタに別のアドレスを代入できてしまうが、参照ではそのようなことはない
  • ポインタベースの参照渡しでは、間接参照が必要だが、参照では不要
void ref_sort() 
{
    int nums[] = { 2, 34, 656, 767, 893, 123, 5, 7, 892, 4, 6, 81, 1134, 56, 3 };
    int len = sizeof(nums) / sizeof(nums[0]);

    for (int i=0; i<len; i++) {
        for (int j=i; j<len; j++) {
            // 引数として値自身(参照)を渡す
            ref_order(nums[i], nums[j]);        
        }
    }
    for (int i=0; i<len; i++) {
        cout << nums[i] << endl;
    }
}

void ref_order(int& n, int& m)
{
    int tmp;
    // ポインタを間接参照する必要はない
    if (n > m) {
        tmp = n;
        n   = m;
        m   = tmp;
    } 
}
結果
2
3
4
5
6
7
34
56
81
123
656
767
892
893
1134