如何在不复制和保留std :: string对象的情况下获取C++ std :: string char数据的所有权?

min*_*nsk 10 c++ string buffer iostream c++11

如何在不复制和保留源std :: string对象的情况下获取std :: string char数据的所有权?(我想使用移动语义但在不同类型之间.)

我使用C++ 11 Clang编译器和Boost.

基本上我想做一些与此相当的事情:

{
    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.
}
Run Code Online (Sandbox Code Playgroud)

为了澄清,我确实需要摆脱std :: string:继续前进.该代码处理字符串和二进制数据,并应以相同的格式处理它.我确实想要来自std :: string的数据,因为它来自另一个与std :: string一起使用的代码层.

为了给出更多透视图,我想要这样做:例如,我有一个异步套接字包装器,它应该能够从用户那里获取std :: string和二进制数据进行写入.两个"API"写入版本(将std :: string或行二进制数据)内部解析为相同(二进制)写入.我需要避免任何复制,因为字符串可能很长.

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)
{
    …
}
Run Code Online (Sandbox Code Playgroud)

这个例子中的std :: unique_ptr用于说明所有权转移:任何其他具有相同语义的方法对我来说都没问题.

我想知道这个特定情况的解决方案(使用std :: string char缓冲区)和字符串,流和类似的一般问题:在字符串,流,std容器和缓冲区类型之间接近移动缓冲区的提示.

我还要感谢有关C++设计方法和特定技术的提示和链接,以便在不复制的情况下在不同的API /类型之间传递缓冲区数据.我提到但不使用流,因为我对这个主题感到不稳定.

bam*_*s53 9

如何在不复制和保留源std :: string对象的情况下获取std :: string char数据的所有权?(我想使用移动语义但在不同类型之间)

你不能安全地做到这一点.

对于特定的实现,在某些情况下,您可以做一些非常糟糕的事情,比如使用别名来修改字符串中的私有成员变量,以欺骗字符串使其认为它不再拥有缓冲区.但即使你愿意尝试这一点,也不会一直有效.例如,考虑小字符串优化,其中字符串没有指向保存数据的某个外部缓冲区的指针,数据在字符串对象本身内.


如果要避免复制,可以考虑将接口更改为scheduledWrite.一种可能性是:

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});
}
Run Code Online (Sandbox Code Playgroud)

  • @minsk:想要这样是相当合理的,不幸的是这是不可能的,因为该类的设计不允许这样做。 (3认同)