C++面试中string类的一种正确写法
参考coolshell
并,
1. 添加了sz,表示长度,不需要strlen
2. 添加转移构造函数和转移赋值操作符,可以做右值引用和转移语义
class String {
public:
String() : data(nullptr), sz(0)
{
cout << "Default constructor is called" << endl;
}
String(const char * str)
{
sz = strlen(str);
init_data(str);
cout << "(const char*) constructor is called, this->data: " << data << endl;
}
String(const String & rhs)
{
sz = rhs.sz;
init_data(rhs.data);
cout << "Copy constructor is called, this->data: " << data << endl;
}
String & operator=(String & rhs)
{
if (this != &rhs) {
sz = rhs.sz;
init_data(rhs.data);
}
cout << "Copy operator is called, this->data: " << data << endl;
return *this;
}
String(String && rhs)
{
data = rhs.data;
sz = rhs.sz;
rhs.data = nullptr;
rhs.sz = 0;
cout << "Move constructor is called, this->data: " << data << endl;
}
String & operator=(String && rhs)
{
if (this != &rhs) {
if (data) delete[] data;
data = rhs.data;
sz = rhs.sz;
rhs.sz = 0;
rhs.data = nullptr;
}
cout << "Move operator= is called, this->data: " << data << endl;
return *this;
}
~String()
{
if (data) {
cout << "Destructor is called, this->data: " << data << endl;
delete[] data;
}
data = nullptr;
}
const char * c_str() const
{
return data;
}
void swap(String & rhs)
{
std::swap(data, rhs.data);
std::swap(sz, rhs.sz);
}
size_t size() const
{
return sz;
}
private:
char *data;
size_t sz;
void init_data(const char * str)
{
data = new char[sz + 1];
memcpy(data, str, sz);
data[sz] = '\0';
}
};
void foo(String x)
{
cout << "foo: " << x.c_str() << endl;
}
void bar(const String & x)
{
cout << "bar: " << x.c_str() << endl;
}
void bar(const String && x)
{
cout << "bar_right: " << x.c_str() << endl;
}
String baz()
{
String ret("baz");
return ret;
}
void SWAP(String & a, String & b)
{
String tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
int main()
{
String s0("hello");
String s1("world");
String s2(s0);
String s3;
s3 = s1;
foo(s1);
bar(s1);
foo("temporary");
bar("temporary");
String s5 = baz();
std::vector<String> svec;
svec.push_back(s0);
svec.push_back(s1);
svec.push_back(s5);
svec.push_back("good job");
SWAP(s2, s3);
cout << "s2: " << s2.c_str() << endl;
cout << "s3: " << s3.c_str() << endl;
return 0;
}
/**
output:
(const char*) constructor is called, this->data: hello
(const char*) constructor is called, this->data: world
Copy constructor is called, this->data: hello
Default constructor is called
Copy operator is called, this->data: world
Copy constructor is called, this->data: world
foo: world
Destructor is called, this->data: world
bar: world
(const char*) constructor is called, this->data: temporary
foo: temporary
Destructor is called, this->data: temporary
(const char*) constructor is called, this->data: temporary
bar_right: temporary
Destructor is called, this->data: temporary
(const char*) constructor is called, this->data: baz
Copy constructor is called, this->data: hello
Copy constructor is called, this->data: world
Copy constructor is called, this->data: hello
Destructor is called, this->data: hello
Copy constructor is called, this->data: baz
Copy constructor is called, this->data: hello
Copy constructor is called, this->data: world
Destructor is called, this->data: hello
Destructor is called, this->data: world
(const char*) constructor is called, this->data: good job
Move constructor is called, this->data: good job
Move constructor is called, this->data: hello
Move operator= is called, this->data: world
Move operator= is called, this->data: hello
s2: world
s3: hello
Destructor is called, this->data: hello
Destructor is called, this->data: world
Destructor is called, this->data: baz
Destructor is called, this->data: good job
Destructor is called, this->data: baz
Destructor is called, this->data: hello
Destructor is called, this->data: world
Destructor is called, this->data: world
Destructor is called, this->data: hello
**/
goudan-er SHARE · CPP
C++