您的位置:首页 > 其它

解决关于initializer_list对象拷贝的疑问

2016-07-22 16:03 316 查看
C++Primer P198 上说拷贝或赋值一个initializer_list对象不会拷贝列表中的元素,拷贝后,原始列表和副本共享元素。

起初有几个疑问:

①一个是不会拷贝列表中的元素是什么意思,那下面的拷贝操作有什么用?

std::initializer_list<int> ilst = {1,2,6};
std::initializer_list<int> ilst2 = { 1,2,3,4,5 };
ilst = ilst2;


②另一个不会拷贝列表中的元素那又怎么个共享法?

在上面添加一个for循环把ilst的值打印出来

for (auto beg = ilst.begin(); beg != ilst.end(); ++beg)
{
std::cout << *beg << std::endl;
}


运行上面的程序发现,结果是这样的:



③那又产生一个疑问,initializer_list对象的元素永远是常量,那为什么又能改变ilst的内容呢?

琢磨了一下,发现我忽略了一个重要的点,那就是initializer_list对象的本质,书上是这么说的:initializer_list是一种标准库类型,用于表示某种特定类型的值的数组。重要的就是这句话,所以initializer_list对象本质上就是数组。而当我们使用数组的对象时,使用的其实是一个指向数组首元素的一个指针, 这句话也很重要,我们又通常用某个地址来表示从这个地址开始的大小不同的比特串,所以我们通常用数组首元素的地址来表示该数组的内存地址,所以上面的拷贝操作,拷贝的实际上是一个指针指向的内存地址,把ilst2所指向的内存地址拷贝给ilst,从而使得ilst指向ilst2指向的那个内存地址,而这里的ilst2指向的是系统用于存放上面初始化ilst2时所用的常量的一个临时内存地址。

std::initializer_list<int> ilst = {1,2,6};
std::initializer_list<int> ilst2 = { 1,2,3,4,5 };
std::cout << ilst.begin() << " " << ilst2.begin() << std::endl;
ilst = ilst2;
std::cout << ilst.begin() << " " << ilst2.begin() << std::endl;


运行结果:



ilst和ilst2指向了同一个内存地址。

分析到这里,三个问题也就都解决了。

一、initializer_list对象在执行拷贝操作时拷贝的实际上是一个内存地址,所以当然不会拷贝列表中的元素。

二、既然拷贝后,原始initializer_list对象和副本指向的是同一个内存地址,所以可以说是共享元素。

三、上面的赋值操作只是改变了指针所指的内存地址,并没有改变ilst原来所指内存地址上面的值,这就有点像指向常量的指针和常量指针这两种指针的区别。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: