假设您有一个名为Product的类,其定义如下:
class Product
{
public:
Product(const char *name, int i);
Product(Product &&rhs);
Product(const Product &rhs);
~Product();
private:
const char *m_name;
int m_i;
};
然后初始化这样的变量:
auto p = Product{"abc",123};
我认为该标准要求编译器在逻辑上必须执行以下操作:
但是允许编译器对此进行优化,以便直接构造p。
我已经验证了这一点(Visual Studio 2013),实际上,即使我们有自己的自定义(非默认)移动构造函数,编译器也会对此进行优化。这可以。
但是,如果我明确删除了copy-和move-constructor,如下所示:
class Product
{
public:
Product(const char *name, int i);
Product(Product &&rhs) = delete;
Product(const Product &rhs) = delete;
~Product();
private:
const char *m_name;
int m_i;
};
自动括号初始化仍然可以编译。尽管编译器必须防止这种情况,因为不允许复制或移动。
奇怪的是,如果我将删除的copy-和move-constructor设为私有,则如下所示:
class Product
{
public:
Product(const char *name, int i);
~Product();
private:
Product(Product &&rhs) = delete;
Product(const Product &rhs) = delete;
const char *m_name;
int m_i;
};
然后,自动括号初始化不再编译。
error C2248: 'Product::Product' : cannot access private member declared in class 'Product'
这是预期的行为吗?这是Visual Studio 2013(更新3)中的错误吗?
注意:我尝试在ideone上进行编译,并且在复制和移动构造函数被删除(并公开)后,它确实拒绝编译初始化。所以我认为这是Visual Studio的错误。
正如您前面提到的,该标准非常明确,表明这是cl编译器中的错误。您永远无法确定,尽管如果一个编译器在说些什么而其他所有人都不同意,我希望这将是MSVC编译器的许多不符合标准的实现之一。
clang版本3.7(svn-build)的解释:
t.cpp:19:7:{19:11-19:30}: error: call to deleted constructor of 'Product'
[Semantic Issue]
auto p = Product{"abc", 123};
^ ~~~~~~~~~~~~~~~~~~~
t.cpp:8:2: note: 'Product' has been explicitly marked deleted here
[Semantic Issue]
Product(Product &&rhs) = delete;
^
1 error generated.
make: *** [t.o] Error 1
gcc 4.8的解释:
t.cpp: In function ‘int main()’:
t.cpp:19:29: error: use of deleted function ‘Product::Product(Product&&)’
auto p = Product{"abc", 123};
^
t.cpp:8:2: error: declared here
Product(Product &&rhs) = delete;
^
make: *** [build/gcc/t.o] Error 1
还请记住,自MSVC 2013以来,“显式默认和删除的功能”是新功能,其实现尚未完成。好像还不了解move构造函数的= default。
我的猜测是,MSVC 2013不会检查move构造函数,或者只是回退到copy构造函数。
检查MSVC 2015可能会很有趣,因为它似乎已经(完全)实现了这些构造。
JVApen
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句