【问题标题】:Is there a way to get a compiler warning when returning a by-value string_view from a temporary?从临时返回按值 string_view 时,有没有办法获得编译器警告?
【发布时间】:2020-05-10 13:08:39
【问题描述】:

我一直在通过将 c++17 更改应用于一些旧代码来学习它们,发现返回 std::string_view 会产生无声的错误,在我看来,引用临时编译器警告是合适的。有没有办法生成一个?

我使用的是 g++ 9.3.0,编译器标志为 -ggdb -Wall -std=c++17。我还尝试了 clang 和 clang-tidy/clazy,没有任何警告。

首先,我最近了解到,最好只使用std::string_view 替换参数中的const std::string &,而不是作为返回值。 This article 向我解释得很好。不幸的是,我没有看到它通常以这种方式呈现,所以我想知道其他人是否有同样的问题。

(下面代码中的第 1 部分) 我知道尝试返回对临时字符串的非常量引用将无法编译。无论该引用是std::string & 还是std::string_view &,都是如此。

如果我尝试返回对永久字符串 theString 的非常量 std::string_view & 引用,则会出现相同的编译器错误。

(下面代码中的第 2 部分) 我还知道,如果我尝试返回对临时字符串的 const 引用,它将编译,但编译器会提供警告,指出我已返回对临时字符串的引用。与第 1 节一样,无论该引用是 const std::string & 还是 const std::string_view &,都是如此。

与第 1 节一样,如果我尝试返回对永久字符串 theStringconst std::string_view & 引用,则会出现对临时编译器警告的相同引用。

(下面代码中的第 3 节) 如果我尝试从永久对象或对永久对象的引用返回std::string_view,当然,它可以正常工作,但如果我尝试从临时对象返回,它会在没有警告的情况下编译,但它的使用会产生垃圾。

编译器不应该产生与代码第 2 部分中相同的临时警告引用吗?当然,它本身不是参考,但 theString 不是临时的,并且该警告已应用于那里。有没有办法可以产生这样的警告?也许我缺少 g++ 或 clang-tidy 的编译器选项?

#include <string>
#include <string_view>
#include <iostream>

class C1
{
public:
    C1() { theString = "Initial string."; }

    //  produce a temporary std::string
    std::string getS() { return theString; }
    //  Returning string_view works fine if called on a reference to a permenant string.
    std::string &getRef() { return theString; }

//  SECTION1: These won't compile: can't bind non-const lvalue reference to the rvalue
//     std::string &getSref() { return getS(); }
//     std::string_view &getSVref() { return getS(); }
//     std::string_view &getSVref() { return theString; }

//  SECTION2: These produce compiler warning: reference to temporary, and use gives seg fault
    const std::string &getSref() { return getS(); }
    const std::string_view &getSVrefFromTemp() { return getS(); }
    //  also produces compiler warning: reference to temporary, 
    //      even though theString is not temporary
    const std::string_view &getSVrefFromPerm() { return theString; }

//  SECTION3:  
    std::string_view getSVfromPerm() { return theString; }  //  works fine
    std::string_view getSVfromRef() { return getRef(); }    //  works fine
    std::string_view getSVfromTemp() { return getS(); }     //  silent bug.

private:
    std::string theString;
};

int main()
{
    C1 myClass;

//  SECTION2: produces seg fault
//     std::cout << "getSref: \"" << myClass.getSref() << "\"." << std::endl;
//     std::cout << "getSVrefFromTemp: \"" << myClass.getSVrefFromTemp() << "\"." << std::endl;
//     std::cout << "getSVrefFromPerm: \"" << myClass.getSVrefFromPerm() << "\"." << std::endl;

//  SECTION3:  These compile silently.
    //  works fine
    std::cout << "getSVfromPerm: \"" << myClass.getSVfromPerm() << "\"." << std::endl;
    //  works fine
    std::cout << "getSVfromRef: \"" << myClass.getSVfromRef() << "\"." << std::endl;
    //  silent bug prints garbage
    std::cout << "getSVfromTemp: \"" << myClass.getSVfromTemp() << "\"." << std::endl;
}

【问题讨论】:

  • ...even though theString is not temporary 但它必须构造一个临时的std::string_view 以匹配返回类型。
  • @Richard 哦!凉爽的!谢谢!我脑子里突然亮了一点灯。
  • 这就是 ref 限定符的用途。您不需要所有这些不同名称的限定符。通过正确使用 ref 限定符,可以重载相同的 getter 以从左值返回 string_view,并从临时返回字符串。

标签: c++ c++17 compiler-warnings temporary-objects string-view


【解决方案1】:

有没有办法在从临时返回按值 string_view 时获得编译器警告?

有!使用clang 10。对于这个程序:

#include <string>
#include <string_view>

struct C
{
    std::string getS();
    std::string_view getSVfromTemp() { return getS(); }
};

clang-10 发出:

<source>:7:47: warning: returning address of local temporary object [-Wreturn-stack-address]
    std::string_view getSVfromTemp() { return getS(); }    
                                              ^~~~~~

【讨论】:

    猜你喜欢
    • 2015-02-09
    • 2011-03-03
    • 1970-01-01
    • 2020-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    • 1970-01-01
    相关资源
    最近更新 更多