2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C++ ポインタまとめ

Last updated at Posted at 2021-07-28

C++のポインタ一覧

ポインタの使い方とか場面とかをそれぞれ紹介する.
たまに迷うことはある.
C言語とほぼ一緒.

変数へのポインタ

int a = 5;
int *a_p = &a;                    // aのアドレスを代入
cout << "a   :" << a << endl;     // value
cout << "*a_p:" << *a_p << endl;  // value
cout << "&a  :" << &a << endl;    // address
cout << " a_p:" << a_p << endl;   // address

注意
int *a_p = &a;      // *a_p&aを代入しているのでは無い.

の部分は

main
// int *a_p = &a;   // a_p&aを代入している.
int *a_p;
a_p = &a;          

と同じ. ここの理解を間違えているとポインタを理解できない.

int *a_p = &a;   // このように書くことが私は多いが,
int* a_p = &a;     // このように書いた方がいいのかもしれない
int* a_p, b_p;      // b_pint型になってしまう (o o)

配列へのポインタ

main
int array[] = {0, 1, 2, 3, 4, 5, 6};
int *arrPt = array;
cout << "array   :" << array << endl;     //address
cout << "arrPt   :" << arrPt << endl;     //address
cout << "array[0]:" << array[0] << endl;  // value
cout << "*arrPt  :" << *arrPt << endl;    // value(== array[0])
cout << "arrPt[1]:" << arrPt[1] << endl;  // value(== array[1])
// ポインタを加算したら何がおこる?
cout << "*(++arrPt) :" << *(++arrPt) << endl;  // value(== array[1])
cout << "*arrPt     :" << *arrPt << endl;      // value(== array[1])

関数の引数

よくある配列要素のswap関数を例にする.
c++では参照渡しが使えるのでこちらも紹介

void swap1(int *a, int *b) {// ポインタ渡し
    cout << "swap1" << endl;
    cout << " a:" << a << endl;   // address
    cout << "*a:" << *a << endl;  // value
    int t = *a;
    *a = *b;
    *b = t;
}
void swap2(int &a, int &b) {// 参照渡し
    cout << "swap2" << endl;
    cout << &a << endl;  // address
    cout << a << endl;   // value
    int t = a;
    a = b;
    b = t;
}
main
int array[] = {0, 1, 2, 3, 4, 5, 6};
swap1(&array[0], &array[2]);
cout << array[0] << endl;
cout << array[2] << endl;
swap2(array[0], array[2]);
cout << array[0] << endl;
cout << array[2] << endl;

構造体へのポインタ

構造体をポインタとして宣言する時がある.
=> 構造体へのポインタを宣言・定義する時がある
例えば木構造のクラスを作った時に, ノードを構造体とした場合, 子への参照には構造体のポインタを使うだろう.

struct myStruct {
    int cost;
    int index;
    myStruct *next;  // 次の要素を構造体として定義
    myStruct(int c, int i) : cost(c), index(i) {}
};
main
myStruct stu = myStruct(50, 0);
myStruct *stuPtr = new myStruct(100, 1); // newを使う
stuPtr->next = &stu;                  // ポインタでは要素の参照に -> を使う
stu.next = stuPtr;                    //   でなければ           . を使う
cout << stu.cost << endl;             //50
cout << stuPtr->cost << endl;         // 100
cout << stu.next->index << endl;      //1
cout << stuPtr->next->index << endl;  // 0
注意

ポインタで定義する時はnewを用いて, メモリの確保を動的に行う.

myStruct *stuPtr;

みたいに定義していると, コンパイルはできるけれど出力で以下のような文言がでる.

$ zsh: segmentation fault  ./a.out

構造体をポインタっぽく扱う方法(追記)

2件目のコメントよりoperatorを用いた云々の話です。多分こういう事?をおっしゃっている.

struct Node {
    int value;
    Node(int v) : value(v) {
        cout << "called constructor" << endl;
    }
    // ここ
    Node *
    operator->() {
        cout << "called -> operator" << endl;
        return this;  // pointer
    }
    void show() {
        cout << "value is " << value << endl;
    }
};
main
Node node = Node(777);
node->show();
cout << node->value << endl;

コラム:そもそもnewって何なん?

int *x;
x = new int();
*x = 5;
cout << "x :" << x << endl;
cout << "*x:" << *x << endl;

newは指定した型へのメモリを動的に確保してくれる.
型っていうのはクラスとか構造体.
クラスのコンストラクタに引数いらないなら( )はいらん.

cout << "new int():" << new int() << endl; // address
cout << "new int  :" << new int << endl;   // address

最後に

他に何かポインタの使い方があったら書き加える. 気分がのれば
あ、全体のソースコードものせておく。この記事はこれの抜粋

pointerTest.cpp
#include <iostream>
using namespace std;

struct myStruct {
    int cost;
    int index;
    myStruct *next;
    myStruct(int c, int i) : cost(c), index(i) {}
};
struct Node {
    int value;
    Node(int v) : value(v) {
        cout << "called constructor" << endl;
    }
    Node *
    operator->() {
        cout << "called -> operator" << endl;
        return this;  // pointer
    }
    void show() {
        cout << "value is " << value << endl;
    }
};
// ポインタ渡し
void swap1(int *a, int *b) {
    cout << "swap1" << endl;
    cout << " a:" << a << endl;   // address
    cout << "*a:" << *a << endl;  // value
    int t = *a;
    *a = *b;
    *b = t;
}
// 参照渡し
void swap2(int &a, int &b) {
    cout << "swap2" << endl;
    cout << "&a:" << &a << endl;  // address
    cout << " a:" << a << endl;   // value
    int t = a;
    a = b;
    b = t;
}
int main(void) {
    cout << "Variable" << endl;
    int a = 5;
    int *a_p = &a;
    cout << "a   :" << a << endl;     // value
    cout << "*a_p:" << *a_p << endl;  // value
    cout << "&a  :" << &a << endl;    // address
    cout << " a_p:" << a_p << endl;   // address
    cout << endl;
    cout << "Array" << endl;
    int array[] = {0, 1, 2, 3, 4, 5, 6};
    int *arrPt = array;
    cout << "array   :" << array << endl;          //address
    cout << "arrPt   :" << arrPt << endl;          //address
    cout << "array[0]:" << array[0] << endl;       // value
    cout << "*arrPt  :" << *arrPt << endl;         // value
    cout << "arrPt[1]:" << arrPt[1] << endl;       // value == array[1]
    cout << "*(++arrPt) :" << *(++arrPt) << endl;  // value
    cout << "*arrPt     :" << *arrPt << endl;      // value
    cout << endl;
    cout << "Function" << endl;
    swap1(&array[0], &array[2]);
    cout << array[0] << endl;
    cout << array[2] << endl;
    swap2(array[0], array[2]);
    cout << array[0] << endl;
    cout << array[2] << endl;
    cout << endl;
    
    cout << "what's new <classT>" << endl;
    int *x;
    x = new int();
    *x = 5;
    cout << "int *x;" << endl;
    cout << "x = new int();" << endl;
    cout << "*x = 5;" << endl;
    cout << "x :" << x << endl;
    cout << "*x:" << *x << endl;
    cout << "new int():" << new int() << endl;
    cout << "new int  :" << new int << endl;
    cout << endl;
    cout << "Struct Pointer " << endl;
    myStruct stu = myStruct(50, 0);
    myStruct *stuPtr = new myStruct(100, 1);
    stuPtr->next = &stu;
    stu.next = stuPtr;
    cout << stu.cost << endl;             //50
    cout << stuPtr->cost << endl;         // 100
    cout << stu.next->index << endl;      //1
    cout << stuPtr->next->index << endl;  // 0

    Node node = Node(777);
    node->show();
    cout << node->value << endl;
    return 0;
}
2
4
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?