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

C++ C++;-类型的非常量引用的初始化无效,c++,C++,首先,我想说,是的,我在来这里之前用谷歌搜索过这个问题,但没有一个答案是相关的 我偷了下面的代码,因为不管什么原因,没有标准的C++ >代码>修剪< /COD>函数。使用VisualStudio,它编译得很好,我成功地完成了项目的其余部分,并且没有给我任何错误 但是今天早上,我决定尝试手动编译整个项目(使用g++-std=c++11*.cpp),现在突然trim函数产生以下错误: DVD.cpp: In static member function 'static DVD DVD::parseD

首先,我想说,是的,我在来这里之前用谷歌搜索过这个问题,但没有一个答案是相关的

我偷了下面的代码,因为不管什么原因,没有标准的C++ >代码>修剪< /COD>函数。使用VisualStudio,它编译得很好,我成功地完成了项目的其余部分,并且没有给我任何错误

但是今天早上,我决定尝试手动编译整个项目(使用
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));
下面是错误提到的
parseDVD
函数:

(DVD.cpp):

如果我从trim函数中删除所有的
&
,它会工作,但我不希望它不断复制

这让我困惑,因为我知道代码是正确的;它不仅是上述问题的公认答案,而且在VisualStudio中运行良好。

您的
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
)。

为什么VS允许这样做?因此,要使其工作,我需要将
dataStr…
部分指定给命名变量,然后将其传递给
trim
?如上所述,我实际上从上述链接窃取了trim函数;他们是公认的答案(尽管我没有仔细阅读下面的评论)。他可能是为了避免抄袭而通过引用?也许这是他的意图,但可能不会有效果。因为您使用的是C++11,所以我会在需要时按值返回。C++11编译器在适当的时候可以更加有选择性地删除副本。@Carcigenicate:Visual Studio在许多方面都不符合标准,即使是在最新版本中。gcc和clang更严格地遵守语言标准,因此我将使用它们的组合作为衡量是非的更好标准。它们并不完美,但比MSVC更完美。假设它们是自由函数,在头文件中声明静态和内联函数是不常见的。我相信这可能会阻碍链接器减少可执行文件大小的努力,但我不确定。@Neil Kirk我复制了他的代码,但他可能不打算将其直接放在头中。我将摆脱内联;特别是因为他们在我们的教科书中提到显式内联是不受欢迎的。谢谢。如果您想在头文件中使用函数,通常首选内联而不是静态的,除非您有特殊的理由不这样做。不要相信你在课本上读到的每一件事。有什么理由让你更喜欢它吗?性能?头文件中的函数会针对包含在其中的每个源文件重新编译,这虽然较慢,但不可避免,无论是静态的还是内联的。当函数是内联的而不是静态的时,链接器只选择一个版本在最终的exe中创建它(因为它们都是相同的)。然而,使它们静态化,则链接器将它们视为独立的函数,即使它们最终是相同的。所以我不确定在这种情况下链接器是否会优化掉额外的副本。
std::string rID = trim(dataStr.substr(0, preTitlePos - 1));
std::string temp = dataStr.substr(0, preTitlePos - 1);
std::string rID = trim(temp);