通过引用,常量引用,右值引用还是常量右值引用传递? [英] Pass by reference, constant reference, rvalue-reference, or constant rvalue-reference?

查看:108
本文介绍了通过引用,常量引用,右值引用还是常量右值引用传递?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习通过引用传递,这是我所做的测试:

I was learning passing by reference, and here is the test I did:

#include <iostream>

using namespace std;

int i = 0;

//If this is uncommented, compiler gives ambiguous definition error.
//void paramCheck (string s) {
//  cout << ++i << ". Param is var.\n";
//}

void paramCheck (const string& s) {
    cout << ++i << ". Param is const ref.\n";
}

void paramCheck (string& s) {
    cout << ++i  << ". Param is non-const ref.\n";
}

void paramCheck (const string&& s) {
    cout << ++i  << ". Param is const rvalue-reference.\n";
}

void paramCheck (string&& s) {
    cout << ++i  << ". Param is non-const rvalue-reference.\n";
}


int main(int argc, char **argv) {
    //Function call test
    paramCheck("");

    paramCheck(string{""});

    string s3{""};
    paramCheck(s3);

    const string s4{""};
    paramCheck(s4);

    //Illegal
    //string& s{""};
    //paramCheck(s);

    const string& s5{s3};
    paramCheck(s5);

    string&& s6{""};
    paramCheck(s6);

    //Illegal
    //const string&& s{s1};
    //onstFP(s);

    //Reference test
    string a = s3;
    a = "a changed s3";
    cout << s3;

    {
    string& b = s3;
    b = "b changed after assigning s3\n";
    cout << "s3 is now " <<s3;

    b = s4;
    b = "b changed after assigning s4\n";
    cout << "s3 is now " <<s3;
    cout << "s4 is now " <<s4;
    }

    cin.get();
    return 0;
}

这是我得到的结果:

1. Param is non-const rvalue-reference.
2. Param is non-const rvalue-reference.
3. Param is non-const ref.
4. Param is const ref.
5. Param is const ref.
6. Param is non-const ref.
s3 is now b changed after assigning s3
s3 is now b changed after assigning s4
s4 is now

我的问题是:


  1. 如果我们传递一个常量表达式,它总是会触发非-恒定的右值引用?在什么情况下它将触发常量rvalue-reference(以及s6为什么不触发它?)

  1. If we pass a constant expression, it always triggers non-constant rvalue-reference? Under what condition it will trigger constant rvalue-reference (and why s6 is not trigging it?)

为什么非常量引用和常量rvalue-reference是非法的?

Why non-constant reference and constant rvalue-reference are illegal?

我期望a不能更改s3,但是为什么内部作用域中的b可以更改s3?如果向b分配新对象s3就是分配新引用,为什么当我为其分配s4并更改s3且之后s4为空?

I expected a cannot change s3, but why b in the inner scope can change s3? If assigning a new object s3 to b is assigning a new reference, why when I assign s4 to it and s3 got changed and s4 is empty afterwards?

很抱歉提出了太多问题...回答所有问题时,我都会加分:)引用使我的困惑从指针转移到了一个全新的水平。

Sorry for asking too many questions... I will increase the points when all questions are answered :) The reference just brings my confusion from pointer to a whole new level.

我不知道如何提高积分……所以要等2天才有资格获得赏金,然后选择答案。

I don't know how to increase the point... so will wait for 2 days till eligible for bounty then choose the answer.

推荐答案

首先执行代码

paramCheck(""); //constructs a temporary. temporaries bind to `string&&`
paramCheck(string{""}); //constructs a temporary. temporaries bind to `string&&`
string s3{""};
paramCheck(s3); //passes a reference to an existing string: `string&`
const string s4{""};
paramCheck(s4); //passes a reference to an existing string+const: `const string&`
//Illegal
//string& s{""}; //cannot assign a temporary to a non-const l-reference
                 //what would s refer to when the temporary "dies"?
                 //`const string&` would have worked though
//paramCheck(s); //passes a reference to an existing string+const: `const string&`
const string& s5{s3}; //s5 is s3, but with `const`. 
paramCheck(s5); //passes a reference to an existing string+const: `const string&`
string&& s6{""}; //r-references extend the life of temporaries.
paramCheck(s6); //passes a reference to an existing strong: `string&`
//const string&& s{s1}; //temporaries can be extended by `T&&` or `const T&` only.

//Reference test
string a = s3; //a is a _copy_ of s3
a = "a changed s3"; //so changing the copy doesn't effect the origional.
cout << s3; //s3 is still blank, it hasn't changed.

{
string& b = s3; //b isn't really a "reference" to `s3`".  `b` _IS_ `s3`.
b = "b changed after assigning s3\n"; //since `b` IS `s3`, this changes `s3`.
cout << "s3 is now " <<s3;

b = s4; //`b` _IS_ `s3`, so you just changed `s3` again.
b = "b changed after assigning s4\n";
cout << "s3 is now " <<s3;
cout << "s4 is now " <<s4; //s4 is still blank, it hasn't changed.
}

然后是问题:


如果我们传递一个常数表达式,它总是会触发非常数rvalue-reference?在什么条件下将触发恒定的rvalue-reference(以及s6为什么不触发它?)

If we pass a constant expression, it always triggers non-constant rvalue-reference? Under what condition it will trigger constant rvalue-reference (and why s6 is not trigging it?)

现有对象将通过 string& const string& 传递,这取决于它们是否为const。也可以将它们复制到作为 string 。临时将作为 string&& 通过,但也可以复制输入为 string 。有 种触发 const string&& 的方法,但是没有理由这样做,所以没关系。 它们在此处显示

Existing objects will pass as string& or const string& depending on if they're const or not. They can also be copied in as string. Temporaries will pass as string&&, but can also be copied in as string. There are ways to trigger const string&&, but there's no reason to do so ever, so it doesn't matter. They're shown here.


为什么非恒定引用和恒定右值引用是非法的?

Why non-constant reference and constant rvalue-reference are illegal?

该标准明确指出,只有 const string& string&&会延长临时人员的寿命,尽管我我不确定为什么他们也没有提及 string& const string&&

The standard specifically says that only const string& and string&& will extend the lives of temporaries, though I'm not certain why they didn't also mention string& and const string&&.


我期望a不能更改s3,但是为什么内部作用域中的b可以更改s3?如果将新对象s3分配给b时,为什么要分配新引用,为什么当我给s4分配s4并更改s3且之后s4为空?

I expected a cannot change s3, but why b in the inner scope can change s3? If assigning a new object s3 to b is assigning a new reference, why when I assign s4 to it and s3 got changed and s4 is empty afterwards?

您初始化了 b 作为对 s3 的引用。不是副本,而是参考。这意味着 b 现在永远指 s3 ,无论如何。当您键入 b = b在分配s3\n后已更改; 时,与 s3 = b在分配s3后已更改changed完全相同\n; 。当您键入 b = s4; 时,这与 s3 = s4 完全相同。那就是参考。它们不能被重新安置。

You initialized b as a reference to s3. Not a copy, but a reference. That means b now refers to s3 forever, no matter what. when you typed b = "b changed after assigning s3\n";, that's exactly the same as s3 = "b changed after assigning s3\n";. When you typed b = s4;, that's exactly the same as s3 = s4. That's what a reference is. They cannot be "reseated".

这篇关于通过引用,常量引用,右值引用还是常量右值引用传递?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆