类实例化语法
我一直被教导说
1. Class c(arg);
和
2. Class c = arg;
是两个完全等价的陈述,但看看这种情况。
#include <iostream>
class Intermediary {
};
class Left {
public:
Left(const Intermediary &) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
class Right {
public:
// The argument is there just so that the example can work, see below
Right(int) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
operator Intermediary () const {
std::cout << __PRETTY_FUNCTION__ << std::endl;
return Intermediary();
}
};
现在如果我这样做:
Left l = Right(0);
编译器会抱怨
error: conversion from Right to non-scalar type Left requested
但是如果我这样做:
Left l(Right(0));
那么一切都会编译并且输出是
Right::Right(int)
Right::operator Intermediary() const
Left::Left(const Intermediary&)
但是,如果我这样做:
Left l = (Intermediary)Right(0);
那么一切都会再次编译并且输出就像上面的一样。
那么显然
1. Class c(arg);
和
2. Class c = arg;
不一样,但是为什么不一样,又有什么区别呢?我在网上找不到任何关于此的信息。
I've always been taught that
1. Class c(arg);
and
2. Class c = arg;
are two totally equivalent statements, but look at this situation.
#include <iostream>
class Intermediary {
};
class Left {
public:
Left(const Intermediary &) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
class Right {
public:
// The argument is there just so that the example can work, see below
Right(int) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
operator Intermediary () const {
std::cout << __PRETTY_FUNCTION__ << std::endl;
return Intermediary();
}
};
Now if I do this:
Left l = Right(0);
The compiler will complain
error: conversion from Right to non-scalar type Left requested
But if I do this:
Left l(Right(0));
Then everything compiles and the output is
Right::Right(int)
Right::operator Intermediary() const
Left::Left(const Intermediary&)
However, if I do this:
Left l = (Intermediary)Right(0);
then everything compiles again and the output is just like the one above.
So obviously
1. Class c(arg);
and
2. Class c = arg;
are not the same, but why not, and what's the difference? I couldn't find anything about this online.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
事实证明它们并不等同。第一个从
arg
构造出Class c
,而第二个则从arg
构造出Class
> 然后复制构造Class c
。请注意,实现可以省略该副本,而且通常会这样做。这需要从
Right
到Intermediary
的转换,以及从Intermediary
到Left
的转换。标准不允许这两个连续的用户定义转换,您必须至少明确其中之一,如下所示:It turns out they are not equivalent. The first one constructs the
Class c
out of anarg
, while the second one constructs aClass
out of anarg
and then copy-constructsClass c
out of it. Note that the implementation is allowed to ellide that copy, and it usually does.This requires a conversion from
Right
toIntermediary
, and one fromIntermediary
toLeft
. This two sequential user defined conversions are not allowed by the standard, you have to do at least one of them explicit as you do with: