我有很多很多字符串,几乎从未在创建后修改过,对它们的访问时间并不是真正的问题。我必须尽可能减少内存使用量,所以我选择编写一个类而不是使用std::string
,它必须保存额外的数据,如容量和长度,以符合标准。此更改导致内存使用量减少〜%30。
为了实现这一点,我编写了一个类,在内部包装C风格的以null结尾的字符串并管理缓冲区,因此该类只包含一个指针数据成员,它提供了足够的接口,很少访问和使用它,如{ {1}}。
我希望避免使用样板代码,并允许从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*)
的透明转换,因此它会自动成为每个函数的3个版本。
以下方法会产生什么影响:
std::string
如果这不起作用,我可以采用什么策略来解决这个问题?
答案 0 :(得分:1)
以下方法会产生什么影响:
A(const char* p) && ~A() &&
最可能的影响是编译错误,因为标准不允许在c / d-tor上使用ref-qualifiers。
我建议像字符串一样实现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 :(得分:1)
有点类似于user2079303的方法,使用SFINAE,因此我们不会阻碍重载解析:
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;
}
};