对于以下程序:
#include <iostream>
struct Foo
{
Foo() { std::cout << "Foo()\n"; }
Foo(const Foo&) { std::cout << "Foo(const Foo&)\n"; }
~Foo() { std::cout << "~Foo()\n"; }
};
struct A
{
A(Foo) {}
};
struct B : A
{
using A::A;
};
int main()
{
Foo f;
B b(f);
}
海湾合作委员会给出:
$ g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Foo()
Foo(const Foo&)
~Foo()
~Foo()
VS 2017(也在 C++17 模式下)给出:
Foo()
Foo(const Foo&)
Foo(const Foo&)
~Foo()
~Foo()
~Foo()
谁是对的,为什么?
(我们也不要忘记 VS 2017 没有正确执行强制的复制省略。因此,可能只是副本是“真实的”,但 GCC 根据 C++17 规则删除了它,而 VS 则不然……)
Visual Studio 似乎没有实现P0136然而。正确的 C++17 行为是单个副本,原始 C++14 行为是两个副本。
C++14 规则 (N4140:[类.inhctor]) 会解释为:
struct B : A
{
using A::A;
};
as:
struct B : A
{
B(Foo f) : A(f) { }
};
引入的构造函数在 p3 中指定,mem 初始化器在 p8 中等效。因此你会得到两份副本Foo
: 一入B
的合成构造函数和一到A
的真正构造函数。
由于 P0136,C++17 规则非常不同(N4659:[class.inhtor.init]): 在那里,我们直接调用A
的构造函数。这并不是说我们要添加一个新的构造函数B
不再是了——而且它不是一种可以用语言表达的机制。因为我们直接调用A(Foo)
,这只是一份副本而不是两份。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)