C++ 如何使用带有右值引用参数的初始值设定项//为什么不能使用另一个C样式数组变量初始化C样式数组
序言 阅读前请注意,我是C++初学者。我还没有学会所有的(基本的)概念(比如模板),但我正在尝试在学习其他东西之前完全理解一些基础知识 所以请不要提及std::string或std:array、vectors、boost::array以及它们相对于C风格数组的优势。我相信他们的观点是正确的,但这不是重点:) 我现在还知道,有时更倾向于在ctor主体中指定元素,而不是使用其成员初始值设定项列表 我的问题 考虑下面的例子。 当我必须定义一个复制构造函数来初始化main()中声明的character2时,我注意到,在Visual Studio 2017中,IntelliSense显示了3个不同的重载来初始化初始化器列表中的类成员。例如,对于“name”变量,列出的可用重载包括: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
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值初始化器。简短回答:因为你没有通过考试