我有以下代码
#include <iostream>
#include <vector>
struct M {
int a = 0;
int b = 0;
~M(){}
};
std::vector<M> ms;
void met(int i)
{
// This struct 'm' does not get deleted after lifetime of function "met" is over
M m;
m.a = i;
m.b = i * i;
ms.push_back(m);
}
int main()
{
for(int i = 0; i < 10; i++){
met(i);
}
for(int i = 0; i < 10; i++){
std::cout << ms[i].a << " : " << ms[i].b << std::endl;
}
return 0;
}
// OUTPUT
0 : 0
1 : 1
2 : 4
3 : 9
4 : 16
5 : 25
6 : 36
7 : 49
8 : 64
9 : 81
我们知道局部变量的范围是即时代码块的生命周期。在上面的代码中,struct M
的范围是生命周期function met
。但在上面的代码工作正常,因为我们可以看到下面的代码输出。我期待未定义的行为当函数遇到返回main时,必须删除原因M m
。在这种情况下结构有什么特别之处吗?
答案 0 :(得分:3)
事实上,删除了met()中的结构。向量中的那些是复制,在调用push_back()时生成。
答案 1 :(得分:2)
//在“met”函数的生命周期结束后,此结构'm'不会被删除
是的,确实如此。您没有考虑的是您在m
内放置了vector
的副本,并且您的结构具有编译器生成的复制构造函数来制作副本成员价值观。 m
退出时met()
已消失,但vector
仍处于活动状态,因为它具有全局范围,并且您输出vector
之前存储的内容范围。
答案 2 :(得分:0)
将实例变量m
存储到向量中时,不存储该实际实例。会发生什么:
m
并更改其属性。m
的复制构造函数。这是一个特殊的构造方法,只要请求隐式副本就会使用它。m
。默认情况下,编译器为每个结构创建一个复制构造函数。默认实现只是(浅)复制每个成员变量一个接一个。因为你的成员变量只是int
,所以它们被复制到向量中新复制的变量。
当你有更大的结构时,需要记住这一点,因为整个结构可以隐式多次复制。