gpt4 book ai didi

c++ - shared_ptr 中 string_view 的返回值优化

转载 作者:行者123 更新时间:2023-12-03 21:05:52 27 4
gpt4 key购买 nike

很难用语言表达所以我会直接跳到半伪代码中。
我有一个下载函数(http GET),它在我的主代码中被多次调用。

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.
}
http_client我正在使用,返回 shared_ptr作为响应,这个响应(我排除了 HTTP 错误处理的代码,假设它是 200。),包含一个 response->body() ,这是一个 std::string_view .
这段代码工作正常,但是,我想确保每次调用/返回此函数时都不会复制下载的数据。
我的主要问题:
  • 我使用的当前代码是否经过返回值优化? (有什么需要做的吗?)
  • 如果没有,我可以返回return response->body(); ?是string_view里面shared_ptr函数返回后有效吗?

  • 我考虑过或在我的旧版本代码中使用的东西:
  • 返回 std::string (使用另一个返回 std::string 作为正文的 http 客户端)。
  • 返回 std::move .
  • 不用写函数,直接把函数体调用这个函数的地方全部替换掉​​,直接用response->body ,避免退货(我讨厌它)。

  • 这样做的正确方法是什么?
    我的工具链:
    Ubuntu 20.04 ( GLIBC 2.31 ), g++ 10.2 , C++20 .

    最佳答案

    您的代码将使用 RVO。它返回一个与函数返回的类型相同的临时变量,它是 cases 之一。其中 RVO 是强制性的。
    当然,它仍然需要一份数据拷贝,作为 string 的一部分。接受 string_view 的构造函数作为论据。
    您不能只是通过 string_view在其自己的。它只不过是一对指向别人数据的指针。根据您的代码,这几乎可以肯定是 response 拥有的数据。 ,它将在您使用 string_view 之前到期那得到了返回。
    你基本上有两个选择。您可以复制数据,也可以保留它。您当前的代码将它复制一次(感谢 RVO),因此对于这种情况,它是我们所能获得的理想选择。但是,还有另一种方法。我们可以返回一个指向字符串 View 的“别名”共享指针。让你的函数返回 std::shared_ptr<std::string_view> ,我们将进行设置以使其发挥作用。shared_ptr<T> 的别名构造函数看起来像这样:

    template <typename Y>
    shared_ptr(const shared_ptr<Y>& custodian, T* ward)
    它创建了一个 shared_ptr当取消引用时,它指向病房。但是,它“拥有”保管人,保管人可以是任何其他类型。直到这个共享指针被销毁后,保管人才会被销毁。
    要使用它,我们必须创建一个包含 shared_ptr<HttpResponse> 的新类。和 body string_view它引用了该响应中的数据。我给它起名字 BodyCustodian使命名尽可能一致。
    struct BodyCustodian
    {
    BodyCustodian(const std::shared_ptr<HttpResponse>& response)
    : response(response)
    , body(response->body()
    { }

    std::shared_ptr<HttpResponse> response;
    std::string_view body;
    };
    现在,在您的代码中,您需要创建以下其中之一 BodyCustodian拥有自己的物体 response (以便正文后面的字符永不过期)和 body这是您要返回的实际 string_view。我们构造其中之一,然后使用别名 shared_ptr构造函数创建指向 body 的指针( BodyCustodian 的一个元素,只要保管人活着就有效),它“拥有”保管人。
    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);
    }
    这个共享指针拥有保管人(使响应保持事件状态),因此 body字符串 View 仍然有效。
    这种方法确实需要在堆上创建一个小对象(大小约为 6 个指针)。这通常很快,并且不依赖于主体的长度(这是您在复制到 std::string 时担心的问题)。我用 make_shared在这里确保我创建了一个 ~6 个指针大小的对象,而不是为一个 BodyCustodian 分配 ~4 个指针的空间。然后为 shared_ptr 提供 ~2 个指针的空间控制块。 make_shared足够聪明,可以一起做。

    关于c++ - shared_ptr 中 string_view 的返回值优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66713239/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com