C ++ - 类型的非const引用的初始化无效

时间:2015-03-23 12:50:49

标签: c++

我想首先说是的,我来这里之前谷歌已经解决了这个问题,但没有一个答案似乎有用。

我从What's the best way to trim std::string?窃取了下面的代码,因为无论出于何种原因,都没有标准的c ++ trim函数。使用Visual Studio,它编译得很好,我设法完成了项目的其余部分而没有给我任何错误。

今天早上,我决定尝试手动编译整个项目(使用g++ -std=c++11 *.cpp),现在突然trim函数产生以下错误:

DVD.cpp: In static member function 'static DVD DVD::parseDVD(std::string, std::string)':
DVD.cpp:65:59: error: invalid initialization of non-const reference of type 'std::string& {aka std::basic_string<char>&}
 from an rvalue of type 'std::basic_string<char>'
 std::string rID = trim(dataStr.substr(0, preTitlePos - 1));

对于使用trim的其他2次,它会产生类似的错误。

以下是“被盗”代码:

(Utils.h):

static inline std::string& ltrim(std::string& s) {
    s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
    return s;
}

// trim from end
static inline std::string& rtrim(std::string& s) {
    s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
    return s;
}

// trim from both ends
static inline std::string& trim(std::string& s) {
    return ltrim(rtrim(s));
}

以下是错误提到的parseDVD函数:

(DVD.cpp):

DVD DVD::parseDVD(std::string dataStr, std::string delimiter) {
    DVD newDVD;
    int preTitlePos = dataStr.find(delimiter, 0);
    int preGenrePos = dataStr.find(delimiter, preTitlePos + 1);

    // V Error is here V
    std::string rID = trim(dataStr.substr(0, preTitlePos - 1));
    std::string rTitle = trim(dataStr.substr(preTitlePos + 1, preGenrePos - preTitlePos - 1));
    std::string rGenre = trim(dataStr.substr(preGenrePos + 1));

    int parsedID = 0;
    //Requirements for a successful parse
    //The ID must be fully numeric, and both of the delimiters must have been found
    if (parseInt(rID, parsedID) && preTitlePos > -1 && preGenrePos > -1) {
        return
            newDVD  .setID(parsedID)
                    .setTitle(rTitle)
                    .setGenre(rGenre);
    }

    return badDVD;
}

如果我从修剪函数中删除了所有&,它可以正常工作,但我宁愿不经常复制。

这让我感到困惑,因为我知道代码是合理的;它不仅是上述问题的公认答案,而且在Visual Studio中工作正常。

1 个答案:

答案 0 :(得分:7)

您的trim()函数预计会对const进行非std::string引用。当你这样调用它时:

std::string rID = trim(dataStr.substr(0, preTitlePos - 1));

您正在使用右值(一个未命名的临时值)调用它。这将具有类型const std::string &,因此它与trim()函数不兼容。为了使其工作,您需要首先将其分配给命名变量:

std::string temp = dataStr.substr(0, preTitlePos - 1);
std::string rID = trim(temp);

在旁注中,您似乎混合了两种从trim()函数返回输出的方法。通常,一个将返回函数的结果(通常按值),或者一个将修改通过引用传递给函数的参数。你的功能同时做到了,这不是典型的。

我会将它们更改为接受输入参数并按值返回结果,或者修改传入的by-reference参数(并将其返回类型更改为void)。