I have project where I will need to create lots of immutable strings. If I am using std::string
, which has huge overhead - about 60-70% against const char *
. On a 64-bit machine, the current implementation uses 8 bytes for the class + the const char *
size. This is the same size as it would be with plain C.
I will also do optimization with union and will put small strings into the pointer itself.
I need to know if I am on right track.
#include <stdio.h>
#include <memory>
#include <string.h>
class String{
public:
String(){};
String(const char *s) : _data(__dup(s)){};
String(const String & other) : String( other.c_str() ){};
String(String && other) = default;
String & operator=(String other){
std::swap(_data, other._data);
return *this;
}
const char *c_str() const{
return _data.get();
}
int cmp(const String & other) const{
if (c_str() == nullptr)
return other ? -1 : 0;
return strcmp(*this, other);
}
operator bool() const{
return c_str();
}
operator const char *() const{
return c_str();
}
bool operator == (const String & other) const{
return cmp(other) == 0;
}
bool operator != (const String & other) const{
return cmp(other) != 0;
}
bool operator > (const String & other) const{
return cmp(other) > 0;
}
bool operator >= (const String & other) const{
return cmp(other) >= 0;
}
bool operator < (const String & other) const{
return cmp(other) < 0;
}
bool operator <= (const String & other) const{
return cmp(other) <= 0;
}
private:
static char *__dup(const char *s){
auto size = strlen(s);
char *copy = new char[size];
memcpy(copy, s, size);
return copy;
}
private:
std::unique_ptr<char[]> _data;
};
void p(String &s){
printf("%s\n", s ? (const char *) s : "[null]");
}
int main(){
String s1; p(s1);
String s2 = { "hello" }; p(s2);
String s3a = s2; p(s3a);
String s3 = std::move(s3a); p(s3);
s1 = s3; p(s1);
s1 = "hi"; p(s1);
String a = "aaaa";
String b = "bbbb";
String c = "aaaa";
printf("%s %s\n", a == c ? "Y" : "N", "Y");
printf("%s %s\n", a == b ? "Y" : "N", "N");
printf("%s %s\n", a != b ? "Y" : "N", "Y");
printf("%s %s\n", a < b ? "Y" : "N", "Y");
printf("%s %s\n", a > b ? "Y" : "N", "N");
printf("%s %s\n", a <= b ? "Y" : "N", "Y");
printf("%s %s\n", a >= b ? "Y" : "N", "N");
printf("%s %s\n", a <= c ? "Y" : "N", "Y");
printf("%s %s\n", a >= c ? "Y" : "N", "Y");
return 0;
}
__dup
to return something, right? Also, I generally wouldn't recommend usingprintf
\$\endgroup\$ – Dan Obermiller Jul 23 '15 at 17:40