可能性のある複製:
C++は文字列定数から 'char *'への非推奨の変換
文字列をchar *経由で関数に渡したい。
char *Type = new char[10];
Type = "Access"; // ERROR
しかし、私はこのエラーを受け取ります:
error: deprecated conversion from string constant to 'char*'
どうすれば修正できますか?
タイプを本当に変更したい場合:
char *Type = new char[10];
strcpy( Type, "Access" );
アクセスを変更したくない場合:
const char *Type = "Access";
ただし、CおよびC++のchar配列には多くの問題があることに注意してください。たとえば、newの呼び出しが成功したかどうか、または例外をスローするかどうかは本当にわかりません。また、strcpy()は10文字の制限を超える可能性があります。
したがって、後でタイプを変更する場合は、検討することができます。
std::string Type = "Access";
そして、それを変更したくない場合:
const std::string Type = "Access";
... std::string
を使用する利点は、これらすべての問題に対処できることです。
ここでいくつかのことが行われています。
char *Type = new char[10];
これにより、Type
という名前のchar*
ポインターが作成され、新しく割り当てられた10要素配列の最初の要素を指すように初期化されます。
Type = "Access"; // ERROR
この割り当ては、あなたが思っていることをしません。 6文字の文字列"Access"
(終端の'\0'
を含む7文字)を作成した配列にコピーしません。代わりに、その配列の最初の要素にpointerをポインターType
に割り当てます。それには2つの問題があります。
最初に、Type
の以前の値を上書きします。今割り当てた10文字の配列には、それを指すものは何もありません。アクセスできなくなったり、割り当てを解除することさえできなくなります。これはメモリリークです。
これはコンパイラが不満を言っていることではありません。
次に、文字列リテラルは静的に割り当てられたconst配列を作成します(「静的に割り当てられた」とは、プログラムの実行全体に存在することを意味します)。 Type
は、const
修飾子で宣言されていません。コンパイラがType
を文字列"Access"
にポイントすることを許可した場合、そのポインターを使用して(変更を試みて)変更できます。
Type = "Access";
Type[0] = 'a'; // try to change the string to "access"
const
の目的は、読み取り専用のものを変更したり、変更しようとしたりすることを防ぐことです。そのため、constポインターオブジェクトに非constポインター値を割り当てることはできません。
C++でプログラミングしているので、おそらくstd::string
を使用する方が良いでしょう。
文字列をchar *経由で関数に渡したい。
以下は、char *を介して文字列を関数に渡す方法です(関数シグネチャの必須のconst
キーワードに注意してください)。
#include <iostream>
void f(const char* p) {
std::cout << p << "\n";
}
int main() {
f("Access");
}
しかし、既存の関数を呼び出していて、その署名を変更できない場合はどうでしょうか?
関数が引数ポインターを介して書き込みを行わないという外部保証がある場合、
#include <iostream>
void f(char* p) {
std::cout << p << "\n";
}
int main() {
f(const_cast<char*>("Access"));
}
一方、関数が文字列に書き込む場合、文字列にスペースを割り当てる必要があります。
#include <iostream>
void f(char* p) {
*++p;
std::cout << p << "\n";
}
int main() {
// Allocate read-write space on the heap
char *p = new char[strlen("Access"+1)];
// Copy string to allocated space
strcpy(p, "Access");
f(p);
delete p;
}
または、
#include <iostream>
void f(char* p) {
*++p;
std::cout << p << "\n";
}
int main() {
// Allocate read-write space on the stack
char arr[] = "Access";
f(arr);
}
しかし、これまでの最善の方法は、ポインタのミスヘガ全体を回避することです。
#include <iostream>
void f(const std::string& p) {
std::cout << p << "\n";
}
int main() {
f("Access");
}
ここには、コーディングの問題ではなく、基本的な操作の問題があります。
Cのchar配列の内容を変更する場合、-代入演算子を使用しないでください。代わりに、基になるポインターの値が変更されます。うん.
代わりに、C文字列ライブラリルーチンを使用することになっています。たとえば、strcpy (Type, "Access");
は、文字列リテラル "Access"を文字配列にコピーし、最後に重要なヌル文字を付けます。
(タグが示すように)C++を使用している場合は、おそらくstd::string
charの配列の代わりに。割り当ては、期待どおりに機能します。