¿Cómo puedo tomar posesión de un C++ std::string char datos sin copiar y mantener el objeto std::string?

¿Cómo puedo tomar posesión de un C++ std::string char datos sin copiar y mantener el objeto std::string?


¿Cómo puedo tomar posesión de los datos de std::string char sin copiar y sin mantener el objeto std::string de origen? (Quiero usar semántica móvil pero entre diferentes tipos).


Uso el compilador de C++11 Clang y Boost.


Básicamente quiero hacer algo equivalente a esto:


{
std::string s(“Possibly very long user string”);
const char* mine = s.c_str();
// 'mine' will be passed along,
pass(mine);
//Made-up call
s.release_data();
// 's' should not release data, but it should properly destroy itself otherwise.
}

Para aclarar, necesito deshacerme de std::string:más adelante. El código trata con datos binarios y de cadena y debe manejarlos en el mismo formato. Y quiero los datos de std::string, porque provienen de otra capa de código que funciona con std::string.


Para dar más perspectiva donde me encuentro con querer hacerlo:por ejemplo, tengo un envoltorio de socket asíncrono que debería poder tomar datos std::string y binarios del usuario para escribir. Ambas versiones de escritura "API" (que toman std::string o datos binarios de fila) se resuelven internamente en la misma escritura (binaria). Debo evitar cualquier copia ya que la cadena puede ser larga.


WriteId     write( std::unique_ptr< std::string > strToWrite )
{
// Convert std::string data to contiguous byte storage
// that will be further passed along to other
// functions (also with the moving semantics).
// strToWrite.c_str() would be a solution to my problem
// if I could tell strToWrite to simply give up its
// ownership. Is there a way?
unique_ptr<std::vector<char> > dataToWrite= ??
//
scheduleWrite( dataToWrite );
}
void scheduledWrite( std::unique_ptr< std::vecor<char> > data)
{

}

std::unique_ptr en este ejemplo para ilustrar la transferencia de propiedad:cualquier otro enfoque con la misma semántica está bien para mí.


Me pregunto acerca de las soluciones para este caso específico (con std::string char buffer) y este tipo de problema con cadenas, flujos y similares en general:consejos para abordar el movimiento de búferes entre cadenas, flujos, contenedores estándar y tipos de búfer.


También agradecería consejos y enlaces con enfoques de diseño de C++ y técnicas específicas cuando se trata de pasar datos de búfer entre diferentes API/tipos sin copiar. Menciono pero no uso transmisiones porque estoy inestable en ese tema.


Algunas respuestas de código


{
std::string s(“Possibly very long user string”);
const char* mine = s.c_str();
// 'mine' will be passed along,
pass(mine);
//Made-up call
s.release_data();
// 's' should not release data, but it should properly destroy itself otherwise. }
WriteId
write( std::unique_ptr<
std::string >
strToWrite ) {
// Convert std::string data to contiguous byte storage
// that will be further passed along to other
// functions (also with the moving semantics).
// strToWrite.c_str() would be a solution to my problem
// if I could tell strToWrite to simply give up its
// ownership. Is there a way?
unique_ptr<std::vector<char>
>
dataToWrite= ??
//
scheduleWrite( dataToWrite );
} void scheduledWrite( std::unique_ptr<
std::vecor<char>
>
data) {
… }
template<typename Container>
void scheduledWrite(Container data) {
// requires data[i], data.size(), and &data[n] == &data[0] + n for n [0,size)
… } // move resources from object owned by a unique_ptr WriteId write( std::unique_ptr<
std::vector<char>
>
vecToWrite) {
scheduleWrite(std::move(*vecToWrite));
} WriteId write( std::unique_ptr<
std::string >
strToWrite) {
scheduleWrite(std::move(*strToWrite));
} // move resources from object passed by value (callers also have to take care to avoid copies) WriteId write(std::string strToWrite) {
scheduleWrite(std::move(strToWrite));
} // assume ownership of raw pointer // requires data to have been allocated with new char[] WriteId write(char const *data,size_t size) // you could also accept an allocator or deallocation function and make ptr_adapter deal with it {
struct ptr_adapter {
std::unique_ptr<char const []>
ptr;
size_t m_size;
char const &operator[] (size_t i) { return ptr[i];
}
size_t size() { return m_size;
}
};
scheduleWrite(ptr_adapter{data,size});
}
struct charbuffer {   charbuffer()   {}    charbuffer(size_t n, char c)   : _data(std::make_shared<std::string>(n, c))   {}    explicit charbuffer(std::string&&
str) : _data(std::make_shared<std::string>(str)) {} charbuffer(const charbuffer&
other) : _data(other._data) {} charbuffer(charbuffer&&
other) {
swap(other);
} charbuffer&
operator=(charbuffer other) {
swap(other);
return *this;
} void swap(charbuffer&
other) {
using std::swap;
swap(_data, other._data);
} char&
operator[](int i) {
return (*_data)[i];
}
char operator[](int i) const {
return (*_data)[i];
}
size_t size() const {
return _data->size();
} bool valid() const {
return _data;
} private: std::shared_ptr<std::string>
_data;
};
std::string s("possibly very long user string");
charbuffer cb(std::move(s));
// s is empty now // use charbuffer...
struct MyData {
virtual void * data () = 0;
virtual const void * data () const = 0;
virtual unsigned len () const = 0;
virtual ~MyData () {} };
struct MyStringData : public MyData {
std::string data_src_;
//... };
struct MyBufferData : public MyData {
MyBuffer data_src_;
//... };