为什么不能将圆括号正确地视为构造函数调用?

问题描述

我写了一个move来模仿std::move,并尝试使用新的结构Foo对其进行测试。但是,出了点问题。

.\main.cpp: In function 'int main()':
.\main.cpp:46:7: error: conflicting declaration 'Foo x'
   46 |   Foo(x);
      |       ^
.\main.cpp:43:15: note: previous declaration as 'std::string x'
   43 |   std::string x = "123";
      |               ^

我将代码Foo(x)替换为Foo foo = Foo(x),然后一切正常。 我正在使用MinGW32 g++ 9.2.0,并使用命令g++ main.cpp -std=c++14

进行编译

有关更多详细信息,请参见下面的代码:

#include <iostream>

template <class T>
struct Remove_Reference {
  typedef T type;
};

template <class T>
struct Remove_Reference<T&> {
  typedef T type;
};

template <class T>
struct Remove_Reference<T&&> {
  typedef T type;
};

template <typename T>
constexpr typename Remove_Reference<T>::type&& move(T&& x) noexcept {
  return static_cast<typename Remove_Reference<T>::type&&>(x);
}

struct Foo {
  Foo() {}
  Foo(std::string&& foo) : val(foo) {
    std::cout << "rvalue reference initialize" << std::endl;
  }
  Foo(const std::string& foo) : val(::move(foo)) {
    std::cout << "const lvalue reference initialize" << std::endl;
  }
  std::string val;
};

void call(std::string&& x) {
  std::cout << "rvalue reference: " << x << std::endl;
}

void call(const std::string& x) {
  std::cout << "const lvalue reference: " << x << std::endl;
}

int main() {
  std::string x = "123";

  Foo{x};
  // Foo(x);

  Foo{::move(x)};
  Foo(::move(x));

  call(x);
  call(::move(x));

  return 0;
}

解决方法

此声明:

diskutil apfs listVolumeGroups -plist

不是函数调用,也不是构造函数调用。这只是一个声明,说明Foo(x); 的类型为x。括号在声明符Foo周围是可选的,因此等效于:

x

这当然会产生错误,因为您已经有一个名为Foo x; 的{​​{1}},并且您不能为同一范围内的多个实体提供相同的名称。


请注意表达式

std::string

与上面的声明(带有x)不同。根据使用的上下文,此表达式可能表示不同的含义。


例如,此代码:

Foo(x)

很好。这确实从表达式;复制名为Foo foo = Foo(x); 的变量的初始化,该表达式是根据参数foo构造的临时Foo(x)。 (在这里并不是特别重要,但是从c ++ 17开始,右侧没有临时对象;该对象只是在适当的位置构造)。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...