gpt4 book ai didi

C++ 编译错误用右值 std::string 构造对象

转载 作者:IT老高 更新时间:2023-10-28 22:23:24 24 4
gpt4 key购买 nike

我遇到了一个我什至不知道如何描述的编译错误!这完全让我感到困惑。

情况:

代码尝试在堆栈上创建一个带有右值 std::string 的对象,该右值用 char* 初始化。

代码:

#include <iostream>
#include <string>

class Foo
{
public:
Foo(double d)
: mD(d)
{
}

Foo(const std::string& str)
{
try
{
mD = std::stod(str);
}
catch (...)
{
throw;
}
}

Foo(const Foo& other)
: mD(other.mD)
{
}

virtual ~Foo() {}

protected:
double mD;
};

class Bar
{
public:
Bar(const Foo& a, const Foo& b)
: mA(a)
, mB(b)
{
}

virtual ~Bar() {}

protected:
Foo mA;
Foo mB;
};

int main(int argc, char* argv[])
{
if (argc < 3) { return 0; }

Foo a(std::string(argv[1]));
Foo b(std::string(argv[2]));

Bar wtf(a, b);
}

编译器错误:

>g++ -std=c++11 wtf.cpp
wtf.cpp: In function ‘int main(int, char**)’:
wtf.cpp:58:17: error: no matching function for call to ‘Bar::Bar(Foo (&)(std::string*), Foo (&)(std::string*))’
Bar wtf(a, b);
^
wtf.cpp:38:9: note: candidate: Bar::Bar(const Foo&, const Foo&)
Bar(const Foo& a, const Foo& b)
^
wtf.cpp:38:9: note: no known conversion for argument 1 from ‘Foo(std::string*) {aka Foo(std::basic_string<char>*)}’ to ‘const Foo&’
wtf.cpp:35:7: note: candidate: Bar::Bar(const Bar&)
class Bar
^
wtf.cpp:35:7: note: candidate expects 1 argument, 2 provided
>

你也不会相信/a 解决方法是什么(或者至少不相信)。如果我在我的右值 std::string 上调用 substr(0),编译器就会被安抚。但我不明白为什么这会有所作为。毕竟……

std::string(argv[1]).substr(0)

...本身仍然是一个右值。我不明白为什么它与编译器的观点不同。

即对 main(...) 的以下更改允许编译成功:

int main(int argc, char* argv[])
{
if (argc < 3) { return 0; }

Foo a(std::string(argv[1]).substr(0));
Foo b(std::string(argv[2]).substr(0));

Bar wtf(a, b);
}

几个额外的数据点:

  • 在没有 C++11 的情况下编译没有区别(我只包含它是为了访问 std::stod(...),这不是重点)。
  • g++ (GCC) 5.4.0。
  • 编译环境是cygwin。
  • 我已尝试修改 Bar 的构造函数以采用 std::string(而不是 std::string&)——它不会影响编译错误。

渴望知道这个问题是什么。这感觉太离谱了。

感谢您的帮助。

最佳答案

这是 most vexing parse 的一个不太常见的示例.声明

Foo a(std::string(argv[1]));

没有用字符串参数调用 Foo 的构造函数;相反,它声明 a 是一个函数,采用 1 个 std::string 数组(调整为指向 std::string 的指针) 并返回 Foo。这就是错误消息提到 Foo (&)(std::string*) 类型的原因:这是编译器认为 ab 的类型> 是。 (消息中的 (&) 仅表示它是一个左值。)

添加 .substr(0) 可以消除声明的歧义,使其不能被解析为函数声明。

大括号初始化是一种更优雅的解决问题的方法:

Foo a{std::string(argv[1])};

关于C++ 编译错误用右值 std::string 构造对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38989211/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com