3

我是 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);
}
4

3 回答 3

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是一个没有别名的唯一对象)。它也更容易阅读。

于 2013-01-03T02:19:37.087 回答
1

没有标准的方法来获取 a 的基础数据的所有权std::string。通常,应该改为返回一个字符串对象本身或让调用者传入一个引用,例如

void f(std::string& s) {
    s = read_str();
}
于 2013-01-03T01:54:13.650 回答
0

这个问题是模棱两可的,但下面的例子应该说明所有的选择。最后一个可能是你想要的,它是 C++11 中添加的一个新特性(std::move和右值引用)。

这允许您将缓冲区转移到相同类型的新对象,但您永远无法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 ) ) {}
};
于 2013-01-03T02:22:25.803 回答