【问题标题】:what's wrong with this anonymous constructor call?这个匿名构造函数调用有什么问题?
【发布时间】:2021-01-31 09:19:02
【问题描述】:

以下代码在 GCC 和 MSVC 下编译良好:

#include <string>

class C
{
public:
   C(const std::string&) { }
};

void f()
{
    std::string s;
    const std::string& sr = s;
    C c = C(sr);
}

此外,如果我用这个替换(整个)最后一行,两个编译器都会接受它:

(C(sr));

但是,如果我将最后一行替换为:

C(sr);

编译器报告如下:

海合会:

$ c++ --std=c++17 yo.cpp
yo.cpp:在函数‘void f()’中:
yo.cpp:13:9: 错误:声明冲突“C sr”
C(sr);
^
yo.cpp:12:24: 注意:之前的声明为‘const string& sr’
const std::string& sr = s;

MSVC:

cl /std:c++17 Source.cpp
Microsoft (R) C/C++ 优化编译器版本 19.16.27043 for x64
版权所有 (C) 微软公司。保留所有权利。
源码.cpp
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\include\xlocale(319):警告 C4530:使用了 C++ 异常处理程序,但未启用展开语义。指定 /EHsc
Source.cpp(14): 错误 C2040: 'sr': 'C' 与 'const std::string &' 的间接级别不同
Source.cpp(14):错误 C2512:“C”:没有合适的默认构造函数可用
Source.cpp(3): 注意:见 'C' 的声明

【问题讨论】:

  • 我不确定你的意思。这从未在 C++ 中编译过。而C(sr) 不是构造函数调用,实际上就像你写了C sr;。现在你可以看到这是一个重新声明,这是不允许的。
  • @cigien,抱歉,请参阅我的最新编辑。点击提交后我做了更多的实验。 (在仔细检查后也删除了关于C++17的注释。)
  • 是的,我明白了。我已经在下面回答了。
  • 稍微麻烦的 Parse 再次来袭
  • 这是一个关于“Most Vexing Parse”的剧 :) 这不是一个官方术语,它用于描述这样的情况,人类看到一些代码,并且它很明显 对他们来说意味着什么,但编译器不同意。有一些这种性质的例子,根据你对 c++ 的熟悉程度,它们可能或多或少让你烦恼:)

标签: c++


【解决方案1】:

此声明:

C(sr);

没有调用构造函数。语法实际上是一个名为 sr 类型为 C 的变量的声明,在声明符 sr 周围有额外的冗余括号。

由于sr 已经被声明,你会得到一个错误。

另一方面,在此声明中:

(C(sr));

表达式C(sr) 实际上被解析为C 对象的初始化,其中sr 作为参数传递。创建的临时 C 对象随后在完整表达式的末尾被销毁。

【讨论】:

  • C{sr}; 是另一种选择。从技术上讲,它不是构造函数调用,它是创建对象的请求,可能涉及调用构造函数。 (例如,在 C++20 中,如果 C 是一个聚合,则 (C(sr)); 继续聚合初始化并且没有构造函数调用)
  • 我不讨厌 C++ 的很多方面。我现在讨厌这个。 ?
  • @cigien 直到我们到达对象列表初始化具有与相同参数的括号初始化不同的行为...(例如std::vector
  • @M.M 是的,但我认为将其添加到答案中将是题外话,并且对于解释解析问题不是很有用。编辑更好吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-16
  • 2010-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多