web-dev-qa-db-ja.com

constポインタをポインタに割り当てます

なぜ私はこれを行うことができないのですか?

char* p = new char[10];

void SetString(char * const str)
{
    p = str;
}


SetString("Hello");

Charへのconstポインターがありますが、constポインターを別のポインターに割り当てられないのはなぜですか?

それを別のポインタに割り当てることによって、charポインタのconst-nessに本質的に違反していないので、それは非論理的に思えます。それともあなたですか?

編集:これをコンパイルすると、「エラーC2440: '=': 'char * const * __w64'から 'char *'に変換できません」と表示されます。

(私は読んでいる本から概念を理解しようとしています。コードをコンパイルすることができません。

コード:

int _tmain(int argc, _TCHAR* argv[])
{

    MyString *strg = new MyString(10);
    strg->SetString("Hello, ");

    MyString *secondstr = new MyString(7);
    secondstr->SetString("Tony");

    strg->concat(*secondstr, *strg);

}

CPPファイル:

#include "MyStringClass.h"
#include <string.h>
#include "stdafx.h"

#include "MyStringClass.h"

void MyString::concat(MyString& a, MyString& b)
{
    len = a.len + b.len;
    s = new char[len + 1];
    strcpy(s, a.s);
    strcat(s, b.s);
    delete [] s; 

}

void MyString::SetString(char * const str)
{
    s = str;
}

MyString::MyString(int n)
{
    s = new char[n+1];
    s[n+1] = '\0';
    len = n;
}

ヘッダーファイル:

#include <string.h>
#include <stdio.h>

class MyString
{
private:
    char* s;
    int len;
public:
    MyString(int n = 80);

    void SetString (char * const str);

    void concat (MyString& a, MyString& b);
};
13
Tony The Lion

定数ポインタと定数へのポインタには違いがあります。定数ポインタは、変更できないポインタ(数値-メモリアドレス)です。常に、初期化によって指定された同じオブジェクトを指します。

int * const const_pointer = &some_int_var; // will be always pointing to this var
const_pointer = &some_other_var; // illegal - cannot change the pointer
*const_pointer = 2; // legal, the pointer is a pointer to non-const

定数へのポインターは、ポイントされた値を変更できないポインターです。

const int * pointer_to_const = &some_int_var; // doesn't have to be always pointing to this var
pointer = &some_other_var; // legal, it's not a constant pointer and we can change it
*pointer = 2; // illegal, pointed value cannot be changed

変数にはいつでも定数を割り当てることができます。つまり、constポインターをnon-constポインターに割り当てることができます(a)。 non-constへのポインターをconst(b)へのポインターにキャストできます。ただし、constへのポインターをnon-constへのポインターにキャストすることはできません(c):

int * pointer;
int * const const_pointer = &var;
const int * pointer_to_const;

/* a */
pointer = const_pointer; // OK, no cast (same type)

/* b */
pointer_to_const = pointer; // OK, casting 'int*' to 'const int*'

/* c */
pointer = pointer_to_const; // Illegal, casting 'const int*' to 'int*'

[編集]以下では、これは標準のc ++ではありません。ただし、これは一般的です。[/ EDIT]
文字列リテラル

"Hello"

constへの定数ポインタに変換されます(const char * const):

char *pointer = "Hello"; // Illegal, cannot cast 'const char*' to 'char*'
char * const const_pointer = "Hello"; // Illegal, cannot cast 'const char*' to 'char*'
const char * pointer_to_const = "Hello"; // OK, we can assign a constant to a variable of the same type (and the type is 'const char*')
"Hello" = pointer_to_const; // Illegal cannot re-assign a constant

上記の例では、2番目があなたの場合です。関数の引数として文字列リテラルを渡すときに、pointer-to-non-constpointer-to-constで初期化しようとしました。これらのポインタが定数であるかどうかに関係なく、それらが何を指しているかは問題です。

概要:
1)あるタイプのポインターを別のタイプのポインターにキャストする場合、pointer-to-constをpointer-to-non-constにキャストすることはできません。
2)定数ポインターがある場合、他の定数と同じルールが適用されます。変数に定数を割り当てることはできますが、変数を定数に割り当てることはできません(初期化を除く)。

//編集
GManが指摘したように、C++ 98標準(§4.2/ 2)では、文字列リテラル(定数char配列)を非constcharポインターに暗黙的にキャストできます。これは下位互換性のためです(C言語では定数はありません)。

もちろん、そのような変換は間違いにつながる可能性があり、コンパイラーはルールに違反してエラーを表示します。ただし、互換モードのGCCは警告のみを表示します。

22
adf88