2009-08-17 5 views
90

私は少しCを知っていますが、今はC++を見ています。 私はCの文字列を扱うための配列をchar型に使用されるが、私はC++コードを見ながら、私は文字列型とchar配列の両方を使用した例があります見ている:C++の文字列とchar []型の相違

#include <iostream> 
#include <string> 
using namespace std; 

int main() { 
    string mystr; 
    cout << "What's your name? "; 
    getline (cin, mystr); 
    cout << "Hello " << mystr << ".\n"; 
    cout << "What is your favorite team? "; 
    getline (cin, mystr); 
    cout << "I like " << mystr << " too!\n"; 
    return 0; 
} 

#include <iostream> 
using namespace std; 

int main() { 
    char name[256], title[256]; 

    cout << "Enter your name: "; 
    cin.getline (name,256); 

    cout << "Enter your favourite movie: "; 
    cin.getline (title,256); 

    cout << name << "'s favourite movie is " << title; 

    return 0; 
} 

は(両方の例からhttp://www.cplusplus.com

これは広く尋ねられ、答えられた(明白な?)質問だと思いますが、誰かが正確にC++の文字列を扱うための2つの方法、API i ntegration、それぞれがより良い方法、...)。

ありがとうございます。

+0

: [STD ::文字列対C++のchar *](http://stackoverflow.com/questions/801209/c-char-vs-stdstring ) –

答えて

140

char配列がまさにそれである - 文字の配列:(あなたの例のように)、スタック上に割り当てられている場合

  • 、それは常に例えば占めることになります。それに含まれるテキストの長さにかかわらず256バイトです
  • ヒープに(malloc()または新しいchar []を使用して)割り当てられた場合、後でメモリを解放する必要があり、常にヒープ割り当てのオーバーヘッドが発生します。
  • 256文字を超える文字列を配列にコピーすると、プログラム内でクラッシュしたり、醜いアサーションメッセージを生成したり、説明できない(誤った)動作を引き起こす可能性があります。
  • テキストの長さを決定するには、文字を\ 0文字でスキャンする必要があります。

文字列は、文字配列を含むクラスですが、自動的に管理します。ほとんどの文字列の実装には、16文字の組み込み配列があります(短い文字列はヒープをフラグメント化しないため)、ヒープを長い文字列に使用します。

あなたはこのような文字列のchar配列にアクセスすることができますC++文字列は、埋め込まれた\ 0文字を含むカウントせずにその長さを知って、短いテキストのヒープに割り当てられたchar配列よりも高速であり、あなたを保護することができます

std::string myString = "Hello World"; 
const char *myStringChars = myString.c_str(); 

をバッファオーバーランから。さらに、読みやすく使いやすくなっています。

-

これは、彼がまったく同じコンパイラとC++ランタイム実装を使っていることを確認するために、このようなDLL関数の任意のユーザを必要とするためしかし、C++の文字列は、DLLの境界を越えての使用のために(非常に)適していません彼のストリングクラスは違った振る舞いをする危険がありません。

通常、文字列クラスは呼び出しヒープ上にヒープメモリを解放するため、ランタイムの共有(.dllまたは.so)バージョンを使用している場合にのみメモリを再度解放できます。

要するに、すべての内部関数とメソッドでC++文字列を使用します。 .dllまたは.soを書く場合は、パブリック(dll/so-exposed)関数でC文字列を使用します。

+3

さらに、文字列には、本当にきれいなヘルパー関数がたくさんあります。 –

+1

私はDLL境界について少しは信じていません。非常に特殊な状況下では、潜在的に破損する可能性があります((1つのDLLは他のDLLのものとは異なるバージョンのランタイムと静的にリンクしています)、さらに悪いことが起こる可能性があります)標準のランタイムの共有バージョン(デフォルト)は発生しません。 –

+1

例:公開APIにstd :: string&を持つlibfooというパブリックライブラリのVC2008SP1コンパイル済みバイナリを配布します。誰かあなたのlibfoo.dllをダウンロードし、デバッグビルドを行います。彼のstd :: stringには、動的ストリングのポインタのオフセットを引き起こす追加のデバッグフィールドがあります。 – Cygon

6

文字列型は完全に管理された文字列クラスですが、char []は文字列を表すバイト配列であるCのままです。

APIと標準ライブラリの点では、すべてが文字列で実装されており、char []では実装されていませんが、char []を受け取るlibcの関数はまだたくさんあるので、私はいつもstd :: stringを使います。

効率の面では、管理されていないメモリのローバッファはほとんどの場合、多くの場合高速ですが、たとえば文字列を比較する場合にはstd :: stringが常に最初にチェックするサイズを、 char []文字ごとに比較する必要があります。

6

Arkaitzは、stringが管理型です。これが意味することの意味は、文字列の長さを心配する必要はなく、文字列のメモリを解放または再割り当てすることを心配する必要もありません。

一方、上記の場合のchar[]表記では、文字バッファが256文字に制限されています。そのバッファに256文字を超える文字を書き込もうとすると、あなたのプログラムが所有している他のメモリを上書きすることになります。最悪の場合、自分が所有していないメモリを上書きしようとします。あなたのOSはその場であなたのプログラムを強制終了します。

ボトムライン?文字列はプログラマーにははるかに優れていますが、char []はコンピューターの方がはるかに効率的です。

+3

最悪の場合、他の人がメモリを上書きし、コンピュータ上で悪質なコードを実行します。 [バッファオーバーフロー](http://cwe.mitre.org/data/definitions/120.html)も参照してください。 –

5

古いコードとの互換性を除いてchar *またはchar []を使用する理由は個人的にはわかりません。 std :: stringはC-stringを使用するよりも遅くはありませんが、あなたのために再割り当てを処理する点が異なります。作成時にサイズを設定できるので、必要に応じて再割り当てを避けることができます。インデクシング演算子([])は、一定の時間アクセスを提供します(単語のあらゆる意味において、C文字列インデクサーを使用するのと全く同じことです)。 atメソッドを使用すると、安全性もチェックされます。書き留めない限り、c-stringで取得できないものもあります。あなたのコンパイラは最も頻繁にリリースモードでインデクサの使用を最適化します。 C文字列を使いこなすのは簡単です。削除対削除[]、例外安全性、C-文字列の再割り当て方法などの事柄。

COW文字列、MT用以外のCOWなどの高度な概念に対処する必要がある場合は、std :: stringが必要です。

もしあなたが参照を使用していれば、どこでも可能な限り参照や参照を使用している限り、コピーによってオーバーヘッドが発生することはありません。また、C文字列。

+0

+1 DLLの互換性のような実装上の問題は考慮されませんでしたが、uはCOWを取得しました。 –

+0

私は12バイトのchar配列を知っていますか?それに対して文字列をインスタンス化すると、実際には効率的でない可能性があります。 –

+0

@David:あなたは非常に機密性の高いコードを持っているなら、はい。 std :: stringメンバーの初期化に加えて、std :: string ctorコールをオーバーヘッドとして考えるかもしれません。しかし、早すぎる最適化は、多くのコードベースを不必要にCスタイルにしてしまったので、注意してください。 – Abhay

0

(char *)をstring.begin()と考えてください。基本的な違いは、(char *)はイテレータであり、std :: stringはコンテナです。基本的な文字列に固執すれば、a(char *)はstd :: string :: iteratorが何をするのかを示します。イテレータの利点とCとの互換性を望む場合は(char *)を使用できますが、これは例外でありルールではありません。いつものように、反復子の無効化には注意してください。人々が(char *)が安全でないと言うとき、これは彼らが意味するものです。他のC++イテレータと同じくらい安全です。

1

文字列にはヘルパー関数があり、自動的にchar配列を管理します。文字列を連結することができます。新しい配列にコピーする必要があるchar配列に対しては、実行時に文字列の長さを変更することができます。 char配列は文字列よりも管理が難しく、特定の関数は文字列を入力として受け付けるだけで、配列を文字列に変換する必要があります。文字列を使うほうが、配列を使う必要がないように作られています。配列が客観的に優れていれば、文字列はありません。

0

違いの1つは、ヌルターミネーション(\ 0)です。

CおよびC++では、char *またはchar []はパラメータとして1つのcharへのポインタをとり、メモリ値が0に達するまで(ヌルターミネータと呼ばれることもある)メモリに沿って追跡します。

C++文字列には\ 0文字を含めることができます。

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

using namespace std; 

void NullTerminatedString(string str){ 
    int NUll_term = 3; 
    str[NUll_term] = '\0';  // specific character is kept as NULL in string 
    cout << str << endl <<endl <<endl; 
} 

void NullTerminatedChar(char *str){ 
    int NUll_term = 3; 
    str[NUll_term] = 0;  // from specific, all the character are removed 
    cout << str << endl; 
} 

int main(){ 
    string str = "Feels Happy"; 
    printf("string = %s\n", str.c_str()); 
    printf("strlen = %d\n", strlen(str.c_str())); 
    printf("size = %d\n", str.size()); 
    printf("sizeof = %d\n", sizeof(str)); // sizeof std::string class and compiler dependent 
    NullTerminatedString(str); 


    char str1[12] = "Feels Happy"; 
    printf("char[] = %s\n", str1); 
    printf("strlen = %d\n", strlen(str1)); 
    printf("sizeof = %d\n", sizeof(str1)); // sizeof char array 
    NullTerminatedChar(str1); 
    return 0; 
} 

出力:これは役立つかもしれ

strlen = 11 
size = 11 
sizeof = 32 
Fee s Happy 


strlen = 11 
sizeof = 12 
Fee 
+0

8年前に尋ねられた質問に答えています。 –

+0

@ n.m:はい私はそれを知っています。私が通過するとき、ポイントのほとんどはこれでカバーされ、私は1つの場所で(最大で)すべての回答を得るのを助ける1つのポイントを追加しました。 –

関連する問題