実際には答えではありませんが、コメントに収まらない、ひどく修正したものです。彼が行ったほど多くのコードを書くべきではありません。
安全なオブジェクトのコピーは、それほどひどく間違えたくないものですが、実際にはそれを回避する最善の方法は、もちろん、最初に適切なライブラリクラスを使用することです。とは言うものの、単純なCスタイルの文字列は、他のどの文字列よりも優れた例です。
class Book {
char *nm;
public:
Book(const char *name) : nm(copystr(name)) { /* don't throw an exception! */ }
Book(const Book &o) : nm(copystr(o.nm)) { /* Likewise! */ }
~Book() { delete[] nm; }
Book& operator=(const Book &o) {
// this is called copy-and-swap (CAS). If you absolutely
// have to write this kind of resource-managing code, then
// you will need this technique, because it's the best
// way to provide the strong exception guarantee.
Book cp = o;
swap(cp);
return *this;
}
/* or you can do this:
Book& operator=(Book cp) {
swap(cp);
return *this;
}
*/
void swap(Book &o) {
std::swap(this->nm, o.nm);
// also swap other members
}
};
char *copystr(const char *name) {
if (!name) return 0;
char *newname = new char[strlen(name)+1];
std::strcpy(newname, name);
return newname;
}
「例外をスローしないでください!」を参照してください。コンストラクターで警告しますか?そうすると、弦が漏れてしまうからです。クラス内に明示的な解放を必要とする複数のリソースが必要な場合、それは物事が本当に退屈になるときです。正しいことは、文字列を保持するためだけにクラスを作成し、他のリソースを保持するために別のクラスを作成し、Bookクラスに各タイプのメンバーを1人含めることです。そうすれば、コンストラクターの例外について心配する必要はありません。これは、構築されたメンバーは、それを含むクラスのコンストラクター本体がスローされると破棄されるためです。これを数回実行すると、標準ライブラリとTR1を使用することにかなり熱心になります。
通常、労力を節約するために、クラスをコピー不可にすることから始め、コピーコンストラクターとoperator =を実装するのは、必要であることが判明した場合のみです。
class Book {
char *nm;
public:
Book(const char *name) : nm(copystr(name)) { }
~Book() { delete[] nm; }
private:
Book(const Book &o);
Book& operator=(const Book &o);
};
とにかく、strdup
大きな謎ではありません。「strdup.c」を検索するだけで、非常によく似た実装がいくつかあります(どちらもGNUからのものです)。同じアプローチは通常、他の文字列処理関数でも機能します。一般に、実装に特別なプラットフォーム依存のメカニズムを必要としないものはすべて、「function_name.c」を探してください。おそらく、その実行方法を説明するGNU実装が見つかります。 、そしてどのようにあなたが似ているが異なることをすることができるか。この場合、あなたは彼らのコードから始めて、への呼び出しmalloc
とエラー処理を置き換えます。
http://www.koders.com/c/fidF16762E3999BA95A0B5D87AECB0525BA67CEE45A.aspx
http://cvs.frodo.looijaard.name/viewvc/cgi-bin/viewvc.cgi/public/psiconv/compat/strdup.c?revision=1.1.1.1&view=markup