C++ 隐式 VS 显式转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7099957/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:28:17  来源:igfitidea点击:

Implicit VS Explicit Conversion

c++type-conversion

提问by John Humphreys - w00te

The C++ Standard Library by Nicolai M. Josuttis states:

Nicolai M. Josuttis 的 C++ 标准库指出:

There is a minor difference between

之间有细微的差别

X x;
Y y(x) //explicit conversion

and

X x;
Y y = x; //implicit conversion

Following to say: "The former creates a new object of type Y by using an explicit conversion from type X, whereas the latter creates a new object of type Y by using an implicit conversion."

下面说:“前者通过使用从类型 X 的显式转换创建一个新的 Y 类型对象,而后者通过使用隐式转换创建一个新的 Y 类型对象。”

I'm a little confused about the concepts of explicit vs implicit conversion I guess. In both cases you're taking an X and pushing it into a Y per se - one uses a Y's constructor and one uses the assignment operator though.

我猜我对显式转换和隐式转换的概念有点困惑。在这两种情况下,您都将 X 推入 Y 本身 - 一个使用 Y 的构造函数,一个使用赋值运算符。

What's the difference in how the conversion is treated in these two cases, what makes it explicit/implicit, and how does this tie into making a class constructor defined with the "explicit" key word, if at all?

在这两种情况下如何处理转换有什么区别,是什么使它显式/隐式,以及这与使用“显式”关键字定义的类构造函数(如果有的话)有何联系?

回答by Matteo Italia

one uses a Y's constructor and one uses the assignment operator though.

一种使用 Y 的构造函数,另一种使用赋值运算符。

Nope. In the second case it's not an assignment, it's an initialization, the assignment operator (operator=) is never called; instead, a non-explicitone-parameter constructor (that accepts the type Xas a parameter) is called.

不。在第二种情况下,它不是赋值,而是初始化,赋值运算符 ( operator=) 永远不会被调用;相反,会explicit调用非单参数构造函数(接受类型X作为参数)。

The difference between initialization and assignment is important: in the first case, a new object is being created, and it starts its life with the value that it is being initialized with (hence why a constructor is called), while assignment happens when an object is assigned (~copied) to an object that already existsand already is in a definite state.

初始化和赋值之间的区别很重要:在第一种情况下,正在创建一个新对象,它以初始化时使用的值开始其生命周期(因此调用构造函数的原因),而赋值发生在对象时被分配(~复制)给一个已经存在并且已经处于确定状态的对象

Anyway, the two forms of initialization that you wrote differ in the fact that in the first case you are explicitly calling a constructor, and thus any constructor is acceptable; in the second case, you're calling a constructor implicitly, since you're not using the "classical" constructor syntax, but the initialization syntax.

无论如何,您编写的两种初始化形式的不同之处在于,在第一种情况下您显式调用构造函数,因此任何构造函数都是可以接受的;在第二种情况下,您隐式调用构造函数,因为您没有使用“经典”构造函数语法,而是使用初始化语法。

In this case, only one-parameter constructors not marked with explicitare acceptable. Such constructors are called by some people "converting" constructors, because they are involved in implicit conversions.

在这种情况下,只有没有标记的单参数构造函数explicit是可接受的。这样的构造函数被一些“转换”构造函数的人调用,因为它们涉及隐式转换。

As specified in this other answer, any constructor not marked as explicitcan take part in an implicit conversion for e.g. converting an object passed to a function to the type expected by such function. Actually, you may say that it's what happens in your second example: you want to initialize (=create with a value copied from elsewhere) ywith x, but xfirst has to be converted to type Y, which is done with the implicit constructor.

正如在另一个答案中所指定的那样,任何未标记为的构造函数explicit都可以参与隐式转换,例如将传递给函数的对象转换为该函数期望的类型。其实,你可能会说,这是你的第二个例子发生了什么:你要初始化(=从其他地方复制的价值创造)yx,但x首先必须转换为类型Y,它与隐式构造函数来完成。

This kind of implicit conversion is often desirable: think for example to a string class that has a converting (i.e. non-explicit) constructor from a const char *: any function that receives a stringparameter can also be called with a "normal" C-string: because of the converting constructor the caller will use C-strings, the callee will receive its stringobject.

这种隐式转换通常是可取的:例如,考虑到一个字符串类,它具有来自 a 的转换(即非explicit)构造const char *函数:任何接收string参数的函数也可以用“正常”C 字符串调用:因为调用者将使用 C 字符串的转换构造函数,被调用者将接收其string对象。

Still, in some cases one-parameters constructors may not be appropriate for conversion: usually this happens when their only parameter is not conceptually "converted" to the type of the object being created, but it is just a parameter for the construction; think for example about a file stream object: probably it will have a constructor that accepts the name of the file to open, but it makes no sense to say that such string is "converted" to a stream that works on that file.

尽管如此,在某些情况下,单参数构造函数可能不适合转换:通常当它们的唯一参数没有在概念上“转换”为正在创建的对象的类型时,通常会发生这种情况,但它只是构造的参数;想想一个文件流对象的例子:它可能有一个接受要打开的文件名的构造函数,但是说这样的字符串被“转换”为适用于该文件的流是没有意义的。

You can also find some more complex scenarios where these implicit conversions can completely mess-up the behavior that the programmer expects from overload resolution; examples of this can be found in the answers below the one I linked above.

您还可以找到一些更复杂的场景,这些隐式转换可以完全搞乱程序员期望从重载解析中获得的行为;这方面的例子可以在我上面链接的答案下面找到。

More simply, it can also happen that some constructors may be very heavyweight, so the class designer may want to make sure that they are invoked explicitly. In these cases, the constructor is marked as explicit, so it can be used only when called "explicitly as a constructor" and doesn't take part in implicit conversions.

更简单地说,也可能发生某些构造函数可能非常重量级的情况,因此类设计者可能希望确保显式调用它们。在这些情况下,构造函数被标记为explicit,因此只有在“显式作为构造函数”调用时才能使用它,并且不参与隐式转换。

回答by Ben Voigt

The first form is direct initialization. The second is copy initialization.

第一种形式是直接初始化。第二个是复制初始化

Copy initialization implicitly calls a converting constructor or conversion operator and then explicitly calls a copy constructor (the copy constructor call may be elided, but an accessibility check must still be performed).

复制初始化隐式调用转换构造函数或转换运算符,然后显式调用复制构造函数(可以省略复制构造函数调用,但仍必须执行可访问性检查)。

Consider a third possibility, which is copy-initialization, but the conversion is explicit:

考虑第三种可能性,即复制初始化,但转换是显式的:

Y y = Y(x);

or

或者

Y y = (Y)x;

回答by Puppy

one uses the assignment operator though

虽然使用赋值运算符

No, it does not. It calls the constructor directly.

不,不是的。它直接调用构造函数。

The reason why one is explicit and one is implicit is because implicit conversions can happen when you don't want them to. Explicit ones cannot. The easiest example of this is bool.

一个是显式的,一个是隐式的,这是因为隐式转换可能在您不希望它们发生时发生。显式的不能。最简单的例子是 bool。

Let's say that you invent some type which can be either true or false- like a pointer. Then let's further say that you decide that in order to make life easier for your users, you let it convert to bool implicitly. This is great- right up until the point where one of your users does something dumb.

假设您发明了某种可以为真或为假的类型,例如指针。然后让我们进一步说,您决定为了让用户的生活更轻松,您让它隐式转换为 bool。这很棒 - 直到您的一个用户做了一些愚蠢的事情。

int i = 0;
i = i >> MyUDT();

Oh wait- why does that even compile? You can't shift a MyUDT at all! It compiles because boolis an integral type. The compiler implicitly converted it to a bool, and then to something that can be shifted. The above code is blatantly dumb- we only want people to be able to convert to a bool, not a bool and anything else that a bool might want to do.

哦等等-为什么它甚至可以编译?您根本无法移动 MyUDT!它编译,因为它bool是一个整数类型。编译器将其隐式转换为 bool,然后转换为可以移位的内容。上面的代码显然是愚蠢的——我们只希望人们能够转换为bool,而不是 bool 和 bool 可能想做的任何其他事情。

This is why explicit conversion operators were added to C++0x.

这就是为什么要在 C++0x 中添加显式转换运算符的原因。

回答by pavuluri santhi

The Implicit castingdoesn't require any casting operator. This casting is normally used when converting data from smaller integral types to larger or derived types to the base type.

隐式转换不需要任何转换操作符。这种转换通常用于将数据从较小的整数类型转换为较大的类型或将派生类型转换为基类型时。

int iVal = 100; double dVal = iVal;

内部 iVal = 100; 双 dVal = iVal;

The explicitconverting constructor is preferred to the implicit conversion operator because in the latter case there is an additional call to the copy constructor.Implicit and Explicit converstions

显式转换构造优选的是隐式转换运算符,因为在后一种情况下,存在于复制构造的额外呼叫。隐式和显式转换