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

标签 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));

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

这是“被盗”的代码:

(实用程序.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;
}

如果我从 trim 函数中删除所有的 &,它就可以工作,但我宁愿它不要不断地制作拷贝。

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

最佳答案

您的 trim() 函数需要对 std::string 的非const 引用。当你这样调用它时:

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() 函数返回输出的方法。通常,要么返回函数的结果(通常按值),要么修改通过引用传递给函数的参数。您的功能同时执行这两项操作,这并不典型。

我会将它们更改为采用输入参数并按值返回结果,或者修改您传入的按引用参数(并将它们的返回类型更改为 void)。

关于C++ - 类型的非常量引用的初始化无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29210710/

相关文章:

c++ - 如何在 C++ 客户端实现在 DLL 中声明的方法

c++ - decltype(auto) 在某些情况下与 SFINAE 一起使用?

c++ - SQLAPI++库使用

c++ - OpenCV - OpenCV Mat 等效于 boost 矩阵 array_type

c++ - 读取文件内容时读取未知符号

c++ - 使用 fprintf 打印两个字符串之间的空格

c++ - C++中的赋值运算符模板和复制构造函数

python ctypes,回调函数增强类型是C++引用

c++ - std::lexical_cast - 有这样的事情吗?

c++ - 警告:std::binary_function<int, int, bool>::binary_function() 在静态库 "*.a"中具有不同的可见性(默认)