2012-02-23 27 views
1

std :: stringをchar *に変換する関数を記述しようとしています。 私が書かれている最初のものは、このでした:文字列をchar *に変換する*

char* $ (string str) 
{ 
    char* cstr; 
    const unsigned int length=str.size(); 
    cstr=new char[1000]; 
    for(int i=0;i<length;i++) 
     cstr[i]=str[i]; 
    cstr[length]=0; 
    return cstr; 
} 

しかし、問題は、メモリリークが発生した:のは、私はこれを行うと仮定してみましょう:

char* cstr; 
string str1("hello"),str2("hello2"); 
cstr=$(str1); 
cstr=$(str2); 

このcase.Theでメモリリークが最初にあります割り当てられた文字列は到達可能ではありませんが、参照は失われています。

char* $ (string str) 
{ 
    static char cstr[1000]; 
    const unsigned int length=str.size(); 
    for(int i=0;i<length;i++) 
     cstr[i]=str[i]; 
    cstr[length]=0; 
    return cstr; 
} 

しかし、問題は今、静的char型のフィールドがアクセス可能であることである: は、だから私は、静的な使用して同じにする

char* cstr; 
string str("hello"); 
cstr=$(str); 
$(str)[5]='!'; 

これはpossibileで、第六文字が変更され、これもCされますcstrが指す文字列が変更されます。

const char* $ (string str) 
{ 
    static char cstr[1000]; 
    const unsigned int length=str.size(); 
    for(int i=0;i<length;i++) 
     cstr[i]=str[i]; 
    cstr[length]=0; 
    return cstr; 
} 

問題はchar型のポインタがconstのchar型のポインタに対応していないということですので、私はこれを行うことはできません:

string str("hello"); 
char* cstr; 
cstr=$(str); 

をしかし、私は唯一使用できるのconstを使用して

const charポインタ 私は、戻り値が右のオペランドとしてしか置かれるが、代入の左のオペランドには配置されない関数を持つことです。これはどのように行うことができますか?

私はこれを実行しようとしました:

char* toCharArray(string& str) 
{ 
    std::unique_ptr<char>p(new char[1000]); 
    char* temp=p.get(); 
    for(unsigned int i=0;i<str.size();i++) 
    { 
     *temp=str[i]; 
     temp++; 
    } 
    return p.get(); 
} 

しかし、問題はまだそこにある、私はこれと私はstatic.Sinceにこのようなコードを使用して掲載、他のソリューションとの違いを見ていない:

char* cstr; 
string str("hello"); 
cstr=toCharArray(str); 
toCharArray(str)[0]='o'; 
cout << cstr; 

文字列を変更します( "oello"を出力します)。 問題はまだ解決されません。

+8

あなたは '$'という関数を書いていますか? –

+4

"この場合、メモリリークがあります。最初に割り当てられた文字列には到達できませんが、参照は失われています。"あなたの関数は、クライアントコードを馬鹿から保護することはできません。あなたが 'std :: string'を使ってリークから保護したいのであれば、' char * 'を使って作業すれば、気をつけなければ漏れるかもしれません。唯一の解決策は、スマートポインタを 'char *'に返すことです(特に、配列の場合は 'delete []'ではなく 'delete'を呼び出します)。 –

+0

'cstr'で何をしたいですか?たぶん、あなたの問題はより巧妙な方法で解決できるでしょう。たとえば、const_cast 'を使って' str.c_str() 'から' const'を削除しますか? – jofel

答えて

-3

str.c_str()?コピーが必要な場合はstrdup(str.c_str())となります。

+0

私はこれを使うことができましたが、私は運動のためにこの機能を実装しようとしています。 –

+4

私はこれを十分に速くdownvoteできませんでした。 'strdup(str.c_str())の間違った量は圧倒的です。 –

+0

@ R.MartinhoFernandes手入れを凝らすには? 「私は個人的にC++でC関数を使うのが好きではありません。 –

1

char *を新規作成し、std::stringの内容をコピーする必要があります。

strcpyを使用できます。

0

あなたがメモリリークに驚いている理由私は表示されません。何かのコピーを作っているなら、あなたはどこかに置く必要があります。

すべてのコピーを同じ場所に置くことができます(オーバーフローの危険性があり、クライアントに適切なコピーを取るか、予期しない破損の危険性があります)、または割り当てを行います(彼らはまだフリーズする必要がありますが、少なくともコピーする必要はありません)、またはバッファとサイズを関数に渡すようにします。

真剣に、関数名として$?

+0

名前の関数は意味があるはずですが、私は$がアセンブリの$を使ってレジスタ値を得るときのように何をしているのかを考えていると思います。 私は上記の投稿でSeymourが言ったように、ポータブルではないので、名前を変更します。 –

+0

あなたは完全な質問を読んだことがありますか?私はcharの静的配列を使用しました。 –

+0

はい、私はしました。 malloc/newを使った最初のサンプルです。 charの静的配列には他の問題があります(たとえば、文字列が1kよりも長い場合、クライアントが文字列を複製せず、他の誰かがその関数を使用した後にクライアントが参照する場合など) –

2

割り当てられた配列をstd::unique_ptr<char[]>またはstd::vector<char>のいずれかに戻すことでメモリリークを防ぐことができます。それらが再割り当てされるか範囲外になると、メモリは両方とも解放されます。

char*の内容を指すポインタは、それぞれptr.get()または&vec[0]となります。

ところで、長さが分かっているので、実際には配列の長さはlength+1でなく、1000でなければなりません。固定サイズのバッファは、オーバーランが発生するのを待っています。また、$は、関数の移植可能な名前ではありません。

+0

長さが宣言されたconst、長さ+ 1はコンパイラエラーの可変長配列かどうか? – supertopi

+0

@supertopi:これは問題ありません。何かを 'const'宣言しても、値を使用して停止するわけではありません。' new char [length + 1] 'または' std :: vector v (長さ+ 1) 'である。 –

関連する問題