Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用带有右值引用参数的初始值设定项//为什么不能使用另一个C样式数组变量初始化C样式数组_C++_Arrays_Initializer List_Rvalue - Fatal编程技术网

C++ 如何使用带有右值引用参数的初始值设定项//为什么不能使用另一个C样式数组变量初始化C样式数组

C++ 如何使用带有右值引用参数的初始值设定项//为什么不能使用另一个C样式数组变量初始化C样式数组,c++,arrays,initializer-list,rvalue,C++,Arrays,Initializer List,Rvalue,序言 阅读前请注意,我是C++初学者。我还没有学会所有的(基本的)概念(比如模板),但我正在尝试在学习其他东西之前完全理解一些基础知识 所以请不要提及std::string或std:array、vectors、boost::array以及它们相对于C风格数组的优势。我相信他们的观点是正确的,但这不是重点:) 我现在还知道,有时更倾向于在ctor主体中指定元素,而不是使用其成员初始值设定项列表 我的问题 考虑下面的例子。 当我必须定义一个复制构造函数来初始化main()中声明的character2

序言

阅读前请注意,我是C++初学者。我还没有学会所有的(基本的)概念(比如模板),但我正在尝试在学习其他东西之前完全理解一些基础知识

所以请不要提及std::string或std:array、vectors、boost::array以及它们相对于C风格数组的优势。我相信他们的观点是正确的,但这不是重点:)

我现在还知道,有时更倾向于在ctor主体中指定元素,而不是使用其成员初始值设定项列表

我的问题

考虑下面的例子。 当我必须定义一个复制构造函数来初始化main()中声明的character2时,我注意到,在Visual Studio 2017中,IntelliSense显示了3个不同的重载来初始化初始化器列表中的类成员。例如,对于“name”变量,列出的可用重载包括:

  • char[50](const char[50]&)
  • char[50](char[50]&&&)
  • char[50]()

  • 附属问题1:为什么IntelliSense仅在变量声明为类成员时才允许显示这些重载?(如果在
    main()


    最让我感兴趣的是其中包含右值引用的一个:

    • char[50](char[50]&&&)
      用于'name'变量
    • int[10](int[10]&&&)
      用于“data”变量
    • int(int&&)
      用于'singledata'变量
    现在,如果在初始值设定项列表中使用
    name()
    ,则似乎使用了重载#3。如果我使用
    name(“aaa”)
    ,则似乎使用了重载#1。这让我对其他概念进行了研究:我现在理解了左值、右值和左值引用的概念(但现在对我来说不是太复杂),我无法完全理解右值引用和移动语义的概念

    考虑到我的部分理解,我试图在我的“参数化构造函数2”中声明一个右值引用(然后变成类型为“rvalue reference to int”的左值),并用它初始化“singledata”变量,希望看到初始化器重载#3在IntelliSense中弹出,但它没有。在这种情况下,带有左值参考参数(重载#2)的参数似乎会再次使用。我无法解释

    我被卡住了,这是我的主要问题1:带右值引用参数的初始值设定项何时碰巧用于类成员


    主要问题2:为什么不能使用另一个字符数组初始化字符数组,而可以使用字符串文字表达式? 因为存在纯右值(prvalues),而变量最多只能转换为xvalue表达式

    我知道这绝对不是标准的,但如果我查看disassembly,字符数组的初始化非常简单:

         2:     const char arrchar1[10]("hello");
    01142771 A1 38 9B 14 01       mov         eax,dword ptr [string "hello" (01149B38h)]  
    01142776 89 45 D8             mov         dword ptr [arrchar1],eax  
    01142779 66 8B 0D 3C 9B 14 01 mov         cx,word ptr ds:[1149B3Ch]  
    01142780 66 89 4D DC          mov         word ptr [ebp-24h],cx  
    01142784 33 C0                xor         eax,eax  
    01142786 89 45 DE             mov         dword ptr [ebp-22h],eax 
    
    当前堆栈帧中堆栈分配的空间
    [arrchar1]
    (在我的例子中是
    [ebp-28h]
    )由
    MOV
    指令集(2,实际上,在本例中:移动1个dword表示“hell”,然后移动1个字表示其余),其中静态空间的内容包含“hello”字符串文字

    <>为什么没有C++的方法导致编译后类似的东西,它会执行相同的事情,但是移动一个栈分配空间的内容(另一个数组变量),而不是“移动”一些静态内存?我希望这样:
    char-arrchar2[10](arrchar1)


    示例:

    #include <string.h> // for strcpy
    
    class Character
    {
    public:
        //default constructor
        Character() {};
    
        //parameterized constructor 1
        Character(const char * pname) : // pointer to the string literal must be const (otherwise it is Undefined Behaviour)
            name(), data{ 1, 2, 3 } // mem-initializer-list: 
                                    // - name is initialized with value-initialization (empty expression-list in a pair of parentheses following identifier)
                                    // - (C++11) data is initialized using list-initialization which becomes aggregate-initialization since it is an aggregate (array)
        {
            strcpy_s(name, pname);
        };
    
        //parameterized constructor 2
        Character(const char * pname, int &&val1) :
            name(), data{ 1, 2, 3 }, singledata(val1)
        {
            strcpy_s(name, pname);
        };
    
        //copy constructor
        Character(const Character & tocopy)
            // member initializer list
    
            //:name(),  // >> IntelliSense shows 3 initializer overloads: char [50](const char [50] &) || char [50](char [50] &&) || char [50]()
                        // >> (visible only if the array is declared in a class, no pop up in main...)
    
            : name("aaa"),
    
            //data()    // >> IntelliSense shows 3 initializer overloads: int [10](const int [10] &) || int [10](int [10] &&) || int [10]()
                        // >> (visible only if the array is declared in a class, no pop up in main...)
    
            data{ 1, 2, 3 }
        {
            // ctor body definition
        };
    private:
        char name[50];
        int data[10];
        int singledata;
    };
    
    void main()
    {
    
        Character character1("characterOne"); // the string literal has static storage duration (static memory), passed pointer allocated on stack memory
        Character character2(character1);
        Character character3("characterThree", 3);
    }
    
    #包含//用于strcpy
    类字符
    {
    公众:
    //默认构造函数
    字符(){};
    //参数化构造函数1
    Character(const char*pname)://指向字符串文字的指针必须是const(否则为未定义行为)
    name(),数据{1,2,3}//mem初始值设定项列表:
    //-使用值初始化初始化名称(标识符后面一对括号中的空表达式列表)
    //-(C++11)数据使用列表初始化进行初始化,列表初始化成为聚合初始化,因为它是聚合(数组)
    {
    strcpy_s(名称、名称);
    };
    //参数化构造函数2
    字符(常量字符*pname,int&&val1):
    name(),数据{1,2,3},singledata(val1)
    {
    strcpy_s(名称、名称);
    };
    //复制构造函数
    字符(常量字符和复制)
    //成员初始值设定项列表
    //:name(),//>>IntelliSense显示3个初始值设定项重载:char[50](常量char[50]&)| | char[50](char[50]&&)| | char[50]()
    //>>(仅当数组在类中声明时可见,在main中没有弹出窗口…)
    :名称(“aaa”),
    //data()/>IntelliSense显示了3个初始值设定项重载:int[10](const int[10]&)| int[10](int[10]&&)| int[10]()
    //>>(仅当数组在类中声明时可见,在main中没有弹出窗口…)
    数据{1,2,3}
    {
    //导体体定义
    };
    私人:
    字符名[50];
    国际数据[10];
    int-singledata;
    };
    void main()
    {
    character1(“characterOne”);//字符串文字具有静态存储持续时间(静态内存),传递的指针分配在堆栈内存上
    字符2(字符1);
    字符3(“字符3”,3);
    }
    
    问题1:

    我相信您会问为什么您的
    singledata
    初始化没有调用其r值初始化器。简短回答:因为你没有通过考试