Không thực sự là một câu trả lời, nhưng một sự điều chỉnh để của dirkgently rằng sẽ không phù hợp trong một chú thích: bạn thực sự không nên viết quá nhiều mã như ông đã làm.
Sao chép đối tượng an toàn không phải là điều bạn muốn sai quá, mặc dù trong cuộc sống thực, cách tốt nhất để tránh điều đó dĩ nhiên là sử dụng các lớp thư viện thích hợp ngay từ đầu. Điều đó nói rằng, một chuỗi kiểu C đơn giản là một ví dụ tốt như bất kỳ điều gì khác để thực hành với:
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;
}
Xem "không ném ngoại lệ!" cảnh báo trong constructor? Đó là bởi vì nếu bạn làm, chuỗi sẽ bị rò rỉ. Nếu bạn cần nhiều hơn một tài nguyên trong lớp của bạn yêu cầu giải phóng rõ ràng, đó là khi mọi thứ trở nên thực sự tẻ nhạt. Điều đúng đắn cần làm là viết một lớp chỉ với mục đích giữ chuỗi, và một lớp khác với mục đích giữ tài nguyên khác, và có một thành viên của mỗi loại trong lớp Sách của bạn. Sau đó, bạn không phải lo lắng về các ngoại lệ trong hàm tạo, bởi vì các thành viên đã được xây dựng bị phá hủy nếu phần thân hàm tạo của lớp chứa có ném. Một khi bạn đã làm điều này một vài lần, bạn sẽ khá quan tâm để sử dụng các thư viện chuẩn và TR1.
Thông thường, để tiết kiệm công sức bạn muốn bắt đầu bằng cách làm cho lớp học của bạn không copyable, và chỉ thực hiện các constructor sao chép và operator = nếu nó quay ra bạn cần chúng:
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);
};
Dù sao, strdup
không bí ẩn lớn. Dưới đây là một vài triển khai rất giống nhau (cả từ GNU), chỉ bằng cách tìm kiếm "strdup.c". Cách tiếp cận tương tự thường hoạt động đối với các hàm xử lý chuỗi khác, và nói chung là không yêu cầu các cơ chế phụ thuộc vào nền tảng đặc biệt để thực hiện: tìm "function_name.c" và có thể bạn sẽ tìm thấy một triển khai GNU giải thích cách thực hiện và cách bạn có thể làm những việc tương tự nhưng khác nhau. Trong trường hợp này, bạn bắt đầu với mã của họ và thay thế cuộc gọi đến malloc
và xử lý lỗi.
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
Thông thường, bạn sẽ sử dụng 'std :: chuỗi' nhưng chính xác những gì bạn có ý nghĩa bởi "không có sử dụng thư viện STL C++"? tức là phần nào của thư viện chuẩn mà bạn đang cố gắng tránh (và tại sao)? –
Tại sao bạn không thể sử dụng 'strdup'? Bạn đang yêu cầu một công cụ để làm điều gì đó trong khi từ chối sử dụng lý tưởng. –
đó là một hạn chế về việc chuyển nhượng ... có lẽ tôi nên thêm một thẻ bài tập ở nhà ... và có bởi STL tôi có nghĩa là sử dụng chuỗi – aherlambang