2017-01-12 6 views
1

作成した後でほとんど変更されていない多くの文字列があり、アクセス時間は本当に問題になりません。私はメモリの使用量を最小限に抑えなければならないので、標準に準拠するために容量や長さなどの余分なデータを保持しなければならないstd::stringを使用する代わりに、クラスを書くことにしました。この変更により、メモリ使用量は約%30減少しました。テンポラリの不要な割り当てを避ける、r値デストラクタ

これを達成するために、私はクラスを書くだけで、Cスタイルのヌルで終了する文字列を内部的にラップし、クラスがポインタデータメンバーで構成されるようにバッファを管理します。 std::string

ボイラープレートコードを避け、std::stringからstd::stringへの透過的な変換を許可したいと思います。したがって、一時的なものが必要な場合など、エッジの場合にstd::stringのデータの割り当て/コピーを避けることはできますか?このことを考えてみましょう:

class A { 
public: 
    A(const char* p) : p_{std::strdup(p)} { } 
    ~A() { free(p_); } 

    A& append(const A&); 

private: 
    char* p_; 
}; 

を今すぐ次のコードで:

A a; 
a.append("test"); 

一時オブジェクトが作成され、割り当て、データをコピーします。その後すぐに破壊されます。問題は、A& append(const char*)のようなすべての関数のバージョンを作成せずにこれを避ける方法があるということです。 std::stringの透過的な変換もサポートしたいので、自動的に各機能の3つのバージョンになります。

には、以下のアプローチはどのような効果を持つことになります。

class A { 
public: 
    A(const char* p) : p_{std::strdup(p)} { } 
    A(const char* p) && 
     : p_{p} { 
    } 

    ~A() { free(p_); } 
    ~A() && { /* nothing */ } 

    A& append(const A&); 

private: 
    char* p_; 
}; 

これで問題が解決しない場合、どのような戦略私はこの問題を解決するために適用することができますか?

+0

をA' 'のコピーがあるときは、UBで大きな問題を抱えています製。 – user2079303

+0

@ user2079303これは完全な実装ではなく、私の問題を示す小さなコードです。 – Etherealone

+0

私は 'char *'オーバーロードより優れたものは何も表示されません。それの問題は何ですか? – Quentin

答えて

1

次のアプローチがありますどのような効果:標準のC/D-TORのREF-修飾子を許可していませんので、

A(const char* p) && 
~A() && 

最も可能性の高い効果は、コンパイル・エラーがあります。

私は文字列がやるだけのようA::c_strを実装し、テンプレートから次のヘルパーを使用することをお勧め:

template<class Str> 
const char* c_str_help(const Str& str) { 
    return str.c_str(); 
} 
const char* c_str_help(const char* str) { 
    return str; 
} 

class A { 
    // ... 

    const char* c_str() const { return p_; } 

    template<class Str> 
    A& append(const Str& str) { 
     const char* s = c_str_help(str); 
     // implement using const char* s 
    } 
}; 

PS:私はunique_ptr<char, void(*)(void*)>の代わりに、はるかに簡単な実装のための裸のポインタを使用することをお勧めします。

1

SFINAEとアプローチ、user2079303さんと少し似たので、我々はオーバーロードの解決妨げない:

namespace detail_A { 
    char const *getString(std::string const &str) { 
     return str.c_str(); 
    } 

    char const *getString(char const *str) { 
     return str; 
    } 

    // More `getString`s as needed... 

    template <class T> 
    using enableString = decltype(getString(std::declval<T>())); 
} 

class A { 
// ... 

    template <class T, class = detail_A::enableString<T>> 
    A &append(T const &str) { 
     char const *p = detail_A::getString(str); 

     std::cout << "Appending \"" << p << "\"\n"; 

     return *this; 
    } 
}; 

See it live on Coliru

関連する問題