web-dev-qa-db-ja.com

const char *をchar *に格納する方法は?

私は このコード 期待どおりに機能します:

#define MAX_PARAM_NAME_LEN 32

const char* GetName()
{
    return "Test text";
}

int main()
{
    char name[MAX_PARAM_NAME_LEN];
    strcpy(name, GetName());    

    cout << "result: " << name << endl;
}

結果をchar *に保存したい場合(使用しているフレームワーク内の一部の関数は入力としてchar *のみを使用するため)、strcpyを使用せずに(実用性とコードの可読性、そして学習も)、どうすればよいですか? constを維持すると、これはうまく機能します。

const char* name;
name = GetName();

しかし、私はまだconstを持っています。

char*を使用しようとしています:

char* name;
name = GetName();

invalid conversion from 'const char*' to 'char*'を取得します。この種の改宗の最良の習慣は何ですか?

12
markzzz

_return "Test text";_は、読み取り専用文字列リテラルへのポインタを返します。

_char*_を入力として受け取る関数を使用していて、_const char*_(読み取り専用の文字列リテラルなど)がある場合は、文字列のディープコピーを提供する必要があります。その_const char*_からそのような関数まで。

そうしないと、関数が読み取り専用の文字列を変更しようとすると、実行時に未定義の動作が発生するリスクがあります。

あなたが現在持っているものは十分です。 _std::string_で作業できないと仮定します。 (can _std::string_で作業する場合andすべてのフレームワーク関数が_const char*_入力を受け取る場合は、使用するコードをリファクタリングすることをお勧めします_std::string_、およびその文字列クラスのc_str()メソッドの出力をフレームワーク関数に渡します。)

最後に、フレームワーク関数の一部に_char*_が必要な場合は、いつでも小さなアダプタークラスを作成できます。

_class Adapter
{
public:
    Adapter(const& Adapter) = delete; /*don't try to copy me please*/
    Adapter& operator=(const Adapter& ) = delete; /*don't try to copy me please*/
    Adapter(const char* s) : m_s(::strdup(s))
    {
    }
    ~Adapter() /*free memory on destruction*/
    {
        ::free(m_s); /*use free to release strdup memory*/
    }
    operator char*() /*implicit cast to char* */
    {
        return m_s;
    }
private:
    char* m_s;
};
_

次に、関数void foo(char* c)の場合、foo(Adapter("Hello"/*or any const char* */));を呼び出すことができ、匿名の一時関数に埋め込まれている_char*_を使用して、fooを自由に実行できます。このクラスを拡張して、コンストラクターを_char*_に移動することもできます。その場合、ポインターの浅いコピーのみが取得されます(デストラクタはメモリを削除しません)。

9
Bathsheba

この種の変換の最良の習慣は、コード全体で_std::string_を使用することです。使用しているフレームワークは入力として_const char*_を受け取るため、_std::string_の呼び出しの結果をいつでも渡すことができます: c_str()

_std::string GetName() {
    return "Test text";
}

int main() {
    std::string name = GetName();
    int res = external_framework_function(name.c_str());
    cout << "result: " << res << " for " << name << endl;
}
_

次善の策は、コードで_const char*_を使用することです。

_const char* name = GetName();
_

使用しているフレームワークは_const char*_を取るので、ここでも問題ありません。

非constポインターが必要な場合は、文字列をコピーする方法はありません。あなたはあなたのためにそれをする関数を作ることができます、しかしあなたはあなたがそれから得たコピーを解放する責任があります:

_char* copy(const char* orig) {
    char *res = new char[strlen(orig)+1];
    strcpy(res, orig);
    return res;
}
...
char *name = copy(GetName());
...
delete[] name;
_
15
dasblinkenlight