string_view 指向另一个字符串

Posted

技术标签:

【中文标题】string_view 指向另一个字符串【英文标题】:string_view points to another string 【发布时间】:2019-06-05 16:17:34 【问题描述】:

我正在使用 Boost 1.70 并发现了一个相当令人费解的问题,有时 boost::string_view 似乎指向另一个字符串。

这是创建 boost::string_view 的函数调用,如下所示:

boost::beast::string_view message = "The resource '" + target.to_string() + "' was not found.";
return prepareError(req, message, beast_http::status::not_found);

这是prepareError() 方法,它在真正奇怪的事情发生时被调用。第一个版本在构造字符串变量时使用 message.to_string():

    template<class Body, class Allocator>
    beast_http::response<beast_http::string_body> prepareError(beast_http::request<Body, beast_http::basic_fields<Allocator>>& req,
        boost::beast::string_view message, beast_http::status statusCode) 
        beast_http::response<beast_http::string_body> resstatusCode, req.version();
        res.set(beast_http::field::server, SERVER_VERSION_STRING);
        res.set(beast_http::field::content_type, MIMETYPE_JSON);
        if (_allowCrossOrigin) 
            res.set(beast_http::field::access_control_allow_origin, "*");
        
        res.keep_alive(req.keep_alive());
        int sc = (int)statusCode;
        std::string json = std::string("\n  error_code:") +
                            std::to_string(sc) + std::string(",\n") +
                            std::string("  error_description:\"") +
                            message.to_string() + std::string("\"\n");

        res.body() = json;
        res.prepare_payload();
        return res;
     

此 json 变量将包含以下字符串,例如:

Printing description of json:
(std::__1::string) json = "\n  error_code:404,\n  error_description:\"\n  error_code:404,\n  error_descript\"\n"

这真的很奇怪。在调试器中,消息变量包含一个空字符串。从方法调用中可以看出,这不应该是该字符串的预期结果。

这是相同的方法,唯一的区别是将消息变量(即 string_view)临时分配给 std::string。

    template<class Body, class Allocator>
    beast_http::response<beast_http::string_body> prepareError(beast_http::request<Body, beast_http::basic_fields<Allocator>>& req,
        boost::beast::string_view message, beast_http::status statusCode) 
        beast_http::response<beast_http::string_body> resstatusCode, req.version();
        res.set(beast_http::field::server, SERVER_VERSION_STRING);
        res.set(beast_http::field::content_type, MIMETYPE_JSON);
        if (_allowCrossOrigin) 
            res.set(beast_http::field::access_control_allow_origin, "*");
        
        res.keep_alive(req.keep_alive());
        int sc = (int)statusCode;
        std::string msg = message.to_string();
        std::string json = std::string("\n  error_code:") +
                            std::to_string(sc) + std::string(",\n") +
                            std::string("  error_description:\"") +
                            msg + std::string("\"\n");

        res.body() = json;
        res.prepare_payload();
        return res;
    

这给出了预期的字符串:

Printing description of json:
(std::__1::string) json = "\n  error_code:404,\n  error_description:\"The resource '/zones' was not found.\"\n"

【问题讨论】:

【参考方案1】:

你的错误来自于

boost::beast::string_view message = "The resource '" + target.to_string() + "' was not found.";

您在右侧创建一个临时字符串,并将视图设置为指向它。行结束后,该临时字符串被销毁,您的视图现在指向无效内存。

您需要做的是直接将临时值传递给函数,如下所示:

return prepareError(req, "The resource '" + target.to_string() + "' was not found.", beast_http::status::not_found);

或者,将结果捕获到std::string 变量中,然后将其传递给函数。

【讨论】:

【参考方案2】:

错误来自:

boost::beast::string_view message = "The resource '" + target.to_string() + "' was not found.";

您构建了一个临时的string,它在语句的末尾结束。 所以你有下一行的悬空视图。

你必须直接在那里建立字符串。

【讨论】:

以上是关于string_view 指向另一个字符串的主要内容,如果未能解决你的问题,请参考以下文章

由给定字符串支持的 string_view

删除 std::string_view 的最后一个字符

使用 std::string_view 的子字符串控制台输出 [关闭]

在这种情况下,使用 string_view 会导致不必要的字符串复制吗?

C++ 17:string_view

如何在编译时从 string_view 中删除子字符串?