Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 共享\u ptr中字符串\u视图的返回值优化_C++_Optimization_Object Lifetime_Return Value Optimization - Fatal编程技术网

C++ 共享\u ptr中字符串\u视图的返回值优化

C++ 共享\u ptr中字符串\u视图的返回值优化,c++,optimization,object-lifetime,return-value-optimization,C++,Optimization,Object Lifetime,Return Value Optimization,这很难用文字表达,所以我将直接跳转到半伪代码中 我有一个下载函数(HTTPGET),它在我的主代码中被多次调用 std::string download_data(){ std::shared_ptr<HttpResponse> response = some_http_client->send_request("some_link"); return std::string(response->body()); // response

这很难用文字表达,所以我将直接跳转到半伪代码中

我有一个下载函数(HTTPGET),它在我的主代码中被多次调用

std::string download_data(){
    std::shared_ptr<HttpResponse> response = some_http_client->send_request("some_link");
    return std::string(response->body()); // response->body() is a std::string_view.
}
std::字符串下载\u数据(){
std::shared_ptr response=some_http_client->send_request(“some_链接”);
返回std::string(response->body());//response->body()是std::string_视图。
}
我正在使用的
http\u客户端
返回一个
shared\u ptr
作为响应,这个响应(我排除了http错误处理的代码,假设它是200。)包含一个
response->body()
,它是一个
std::string\u视图

这段代码工作正常,但是,我希望确保每次调用/返回此函数时不会复制下载的数据

我的主要问题:

  • 我使用的当前代码是否受返回值优化的影响?(有什么需要做的吗?)
  • 如果没有,我可以返回
    returnresponse->body()?函数返回后,
    shared\u ptr
    中的
    string\u视图是否有效
我在旧版本代码中考虑或使用的内容:

  • 返回
    std::string
    (另一个http客户端将
    std::string
    作为主体返回)
  • 使用
    std::move
    返回
  • 不用编写函数,只需替换函数体调用该函数的所有位置,直接使用
    响应->函数体
    ,避免返回(我讨厌它)
正确的做法是什么

我的工具链:


Ubuntu 20.04(
GLIBC 2.31
),
g++10.2
C++20
,您的代码将使用RVO。它返回一个与函数返回的类型相同的临时值,这是RVO是必需的函数之一

当然,它仍然需要一份数据副本,作为接受
string\u视图作为参数的
string
构造函数的一部分

您不能只传递
字符串视图
。它只不过是一对指向其他人数据的指针。根据您的代码,这几乎肯定是
response
拥有的数据,在您使用返回的
string\u视图之前,这些数据将过期

你基本上有两个选择。您可以复制数据,也可以保留数据。您当前的代码只复制了一次(多亏了RVO),所以对于这种情况,它是我们所能得到的最理想的。然而,还有另一种方法。我们可以返回一个指向字符串视图的“别名”共享指针。让您的函数返回一个
std::shared_ptr
,我们将对此进行设置

shared\u ptr
的别名构造函数如下所示:

template <typename Y>
shared_ptr(const shared_ptr<Y>& custodian, T* ward)
现在,在您的代码中,您需要创建一个
bodyConservator
对象,该对象保存自己的
响应(以便正文后面的字符永远不会过期)和一个
body
,这是您想要返回的实际字符串视图。我们构造其中一个,然后使用别名
shared_ptr
构造函数创建指向
body
(只要保管人还活着,
body保管人的一个元素就有效)的指针,该指针“拥有”保管人

std::shared_ptr<std::string_view>, download_data(){
    std::shared_ptr<BodyCustodian> custodian = std::make_shared<BodyCustodian>(some_http_client->send_request("some_link"));
    return std::shared_ptr<std::string_view>(custodian, &custodian->body);
}
std::共享数据,下载数据(){
std::shared_ptr保管人=std::make_shared(一些http_客户端->发送请求(“一些链接”);
返回std::shared_ptr(保管人和保管人->主体);
}
这个共享指针拥有保管人(保管人使响应保持活动状态),因此
主体
字符串视图仍然有效


这种方法确实需要在堆上创建一个小对象(大约6个指针大小)。这通常很快,并且不取决于正文的长度(这是您在复制到std::string时担心的问题)。我在这里使用
make_shared
来确保创建一个6指针大小的对象,而不是为
bodycatcher
分配4个指针大小的空间,然后为
shared_ptr
控制块分配2个指针大小的空间
make_shared
足够聪明,可以一起完成这些任务。

我不存储响应,它们会立即被处理和丢弃。但是我可以将std::move()主体放在std::string中并返回它吗?避免复制?这样做不会改变任何事情。
std::move
会将其转换为
string\u视图&
,但是拾取的
string
构造函数只使用
const string\u视图&
,因此它会立即恢复到复制状态。然而,我们在这里讨论的是两个指针的复制,而不是字符的复制。字符的复制发生在
字符串
构造函数中,而不是在参数处理中。如果您只是立即处理并丢弃数据,那么您的用例基本上就是
共享\u ptr
的别名构造函数所支持的。我得到的错误是没有匹配的构造函数,函数的返回值是
std::shared\u ptr
,响应是
std::shared\u ptr
,response->body()返回
string\u视图a上的
std::string\u view
@MaxPaython
是此函数调用的本地调用,当函数返回时它将被销毁,因此指向它的指针将变得无效(因此您必须在堆上分配它)
std::shared_ptr<std::string_view>, download_data(){
    std::shared_ptr<BodyCustodian> custodian = std::make_shared<BodyCustodian>(some_http_client->send_request("some_link"));
    return std::shared_ptr<std::string_view>(custodian, &custodian->body);
}