我是C ++的新手。我假设std::string
使用引用计数来确定何时释放缓冲区。在以下示例中,s
将在f()
返回时释放。如果我想将字符串缓冲区的所有权赋予give_ownership_of
而不释放它,该怎么办?
void f()
{
string s = read_str();
give_ownership_of(s);
}
更新
让我在问题中添加更多细节。实际代码如下所示,
string read_str();
void write_str_async(const char *str, void (*free_fn)(const char*));
void f() {
string s = read_str();
// write_str_async() need to access the buffer of s after f() returns.
// So I'm responsible to keep s alive until write_str_async() calls free_fn to release the buffer when the write is done.
// The PROBLEM here is that s will be released when the variable scope ends. NOTE: I'm not able to change either read_str() or write_str_async() here.
write_str_async(s.c_str(), my_free_fn);
}
答案 0 :(得分:4)
在C ++ 11中,他们添加了类似的内容,称为移动。 std::string
有一个移动构造函数和一个移动赋值运算符。
这里的编译器可以确定s
已经到达其生命周期的末尾,所以不是复制到give_ownership_of
它可以移动,这基本上只是复制几个整数/指针,而不是std::string
的内容。请注意,这仍然比通过引用传递更慢,因此如果引用适合您,则无论如何都应该更喜欢。
https://akrzemi1.wordpress.com/2011/08/11/move-constructor/
我强烈建议不要使用std::shared_ptr
,因为没有实际的所有权共享。
如果您想要明确移动,那么您可以这样做:
give_ownership_of(std::move(s));
请注意,从函数返回值时,您不需要(实际上不应该)使用std::move
。只需正常返回值即可。在许多情况下,编译器可以执行“返回值优化”,这意味着没有副本也没有移动。它类似于通过引用传递值并分配给它,除了它实际上为优化器提供了更多的空间(因为它知道std::string
是一个不包含任何内容的唯一对象)。阅读也更直接。
答案 1 :(得分:1)
没有标准方法来获取std::string
的基础数据的所有权。通常,应该返回一个字符串对象本身或让调用者在引用中传递,例如
void f(std::string& s) {
s = read_str();
}
答案 2 :(得分:0)
问题含糊不清,但下面的例子应说明所有替代方案。最后一个可能是你想要的,它是C ++ 11中添加的一个新功能(std::move
和rvalue引用)。
这允许您将缓冲区传输到相同类型的新对象,但您永远不能完全消除std::string
。您可以忽略string
并将缓冲区内存视为字节,但必须通过销毁string
来执行释放。
// will retain s for duration of function
void give_ownership_of( std::string &s );
// will retain a copy of s for duration of function
void give_ownership_of( std::string s );
struct give_ownership_of {
std::string s;
// will retain a copy of in_s for object lifetime
give_ownership_of( std::string const &in_s ) : s( in_s ) {}
// will transfer buffer of in_s to s and retain that (C++11 only)
// you would write give_ownership_of( std::move( s ) );
give_ownership_of( std::string &&in_s ) : s( std::move( in_s ) ) {}
};