If I understand correctly, you need a class that stores a single pointer to a dynamically allocated string with a length prefix. You can do this by taking advantage of the fact that char* can safely alias something.
The simplest implementation, just to show how this can be done :
class LPS { private: char* ptr; public: LPS() noexcept : ptr(nullptr) {} // empty string without allocation explicit LPS(std::size_t len) { // Allocate everything in one go // new[] gives storage aligned for objects of the requested size or less ptr = new char[sizeof(std::size_t) + len]; // Alias as size_t // This is fine because size_t and char have standard layout *reinterpret_cast<std::size_t*>(ptr) = len; } explicit LPS(char const* sz) { std::size_t len = std::char_traits<char>::length(sz); ptr = new char[sizeof(std::size_t) + len; *reinterpret_cast<std::size_t*>(ptr) = len; std::copy(sz, sz + len, ptr + sizeof(std::size_t)); } LPS(LPS const& that) { if(that.ptr) { ptr = new char[sizeof(std::size_t) + that.size()]; std::copy(that.ptr, that.ptr + sizeof(std::size_t) + that.size(), ptr); } else ptr = nullptr; } LPS(LPS&& that) noexcept { ptr = that.ptr; that.ptr = nullptr; } LPS& operator=(LPS that) { swap(that); return *this; } ~LPS() noexcept { // deleting a null pointer is harmless, no need to check delete ptr; } void swap(LPS& that) noexcept { std::swap(ptr, that.ptr); } std::size_t size() const noexcept { if(!ptr) return 0; return *reinterpret_cast<std::size_t const*>(ptr); } char* string() noexcept { if(!ptr) return nullptr; // the real string starts after the size prefix return ptr + sizeof(std::size_t); } };
R. Martinho Fernandes
source share