简体   繁体   English

将const int和vs int分配给const int&

[英]Assigning double to const int& vs int to const int&

I am trying to understand constant reference in C++ and I stumbled across this problem: 我试图理解C ++中的常量引用,我偶然发现了这个问题:

When I assign double to a const int& and then change the value of the referencing double, the value of my int reference stays constant. 当我将double赋值给const int&然后更改引用double的值时,my int引用的值保持不变。

    double i = 10;
    const int &ref = i;    
    i = 20;

    cout << "i: " << i << endl;      // i = 20
    cout << "&ref: " << ref << endl; // ref = 10

Whereas while assigning int, the value gets changed. 而在分配int时,值会发生变化。

    int i = 10;
    const int &ref = i;    
    i = 20;

    cout << "i: " << i << endl;      // i = 20
    cout << "&ref: " << ref << endl; // ref = 20

What is the reason for this behaviour? 这种行为的原因是什么? My guess is that when assigning double, the implicit conversion to int creates a new object and its reference is then being assigned, however I can't find it written down anywhere. 我的猜测是,当分配double时,隐式转换为int会创建一个新对象,然后分配它的引用,但是我无法在任何地方找到它。

Even though it looks like, ref isn't a reference to i . 虽然它看起来像,但ref不是对i的引用。

double i = 10;
const int &ref = i;   // ***
i = 20;

A reference to an int cannot refer to a double . int的引用不能引用double Therefore, in the marked line, a conversion from a double to an int takes place and the result of conversion is a temporary rvalue. 因此,在标记行中,发生从doubleint的转换,转换结果是临时rvalue。 Normaly, they are destroyed when the full expression they were created in ends. Normaly,当他们在结尾创造出完整的表达时,他们就会被摧毁。 But there's a rule in C++ that allows extending the lifetime of a temporary when it is bound to a reference to const . 但是C ++中有一条规则允许在绑定到const的引用时延长临时的生命周期。 It is extended until the reference dies. 它被延长直到参考死亡。 For that, the compiler actually allocates some memory for it behind the scenes. 为此,编译器实际上在幕后为它分配了一些内存。

The assignment modifies the original object i , the unnamed temporary stays intact. 赋值修改原始对象i ,未命名的临时保持原样。

When you convert the double to an int , the result is an rvalue of type int . double转换为int ,结果是int类型的rvalue。 This temporary value is bound to a constant reference variable, and thus the lifetime of the temporary value is extended to that of the reference variable. 此临时值绑定到常量引用变量,因此临时值的生命周期将扩展为引用变量的生存期。 Changing the original double has no effect on that. 更改原始double对此没有影响。

The compiler can help you a lot only if you remove const from both declarations and attempt to compile the code snippets: 只有从两个声明中删除const并尝试编译代码片段时,编译器才能帮助你很多:

double i = 10;
/*const*/ int &ref = i;    //ERROR - WHY?

This code will give compilation error! 此代码将给出编译错误! Why? 为什么?

But this code: 但是这段代码:

int i = 10;
/*const*/ int &ref = i;   //NO ERROR

will compile fine. 将编译好。

If the first code compiles fine when there is const , why doesn't it compile now (when const is not there)? 如果第一个代码在有const时编译正常,为什么现在不编译(当const不存在时)? What is going on under the hood? 引擎盖下发生了什么?

Well, the reason is, actually int& is a reference type which can refer to an object of type int only, not double , so a temporary object of type int is created out of the expression i (which is double ), but the temporary object cannot bind to int& , so it gives compilation error , but as soon as you put const there, it compiles fine, because a temporary object of type int can bind to const int& . 好吧,原因是,实际上int&是一个引用类型,它只能引用int类型的对象 ,而不是double ,所以int类型的临时对象是从表达式i (它是double )创建的,但是临时对象无法绑定到int& ,因此它会产生编译错误 ,但是只要将const放在那里,就可以很好地编译,因为int类型的临时对象可以绑定到const int&

No such thing happens in the second code — no temporary object is created. 在第二个代码中没有发生这样的事情 - 没有创建临时对象。 So when you set i to 20 , the ref also changes in the second case (as it refers to i ) but in the first case, when you set i to 20 , the ref does not change because ref does not refer to i anymore — it rather refers to the temporary object (which you're not changing!). 所以,当你设置i20时, ref也改变在第二种情况下(因为它是指i ),但在第一种情况下,当你设置i20时, ref没有改变,因为ref 并不是i了-它指的是临时对象(你没有改变!)。 That explains the behaviors of your code snippets. 这解释了代码片段的行为。

Hope that helps. 希望有所帮助。

double i = 10;
const int &ref = i; 

Depending on the compiler you are using this code, as is, could as well give a compilation error. 根据您使用此代码的编译器,也可以提供编译错误。

On a compiler where it throws an error, if you cast it to (int &) you would see undefined behavior, since you are reading an int from a double's location. 在抛出错误的编译器上,如果将其(int &)(int &)您将看到未定义的行为,因为您正在从double的位置读取int。 On a compiler which accepts this line, my best guess is it is creating a temporary variable (an rvalue) and assigning to the int reference, and any changes to the original variable are not reflected in the reference. 在接受此行的编译器上,我最好的猜测是它创建一个临时变量(一个rvalue)并分配给int引用,并且对原始变量的任何更改都不会反映在引用中。

For the reference to work make sure the source data type can be represented by destination data type. 对于工作参考,请确保源数据类型可以由目标数据类型表示。

You can think of an int as a class, and int(double); 您可以将int视为一个类,并将int(double); as a way of constructing an int from a double, you have a const reference to that int, which was constructed from a double. 作为从double构造int的一种方法,你有一个对这个int的const引用,它是从double构造的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM