当编写一些将(部分)数据结构加载到图形内存中的代码时,我对这种意外行为感到惊讶。
我已将代码简化为以下内容:
#include <iostream>
#include <vector>
using namespace std;
struct Data{
int data;
Data(int x){
data = x;
cout<<"+ Data"<<endl;
}
~Data(){cout<<"- Data"<<endl;}
};
struct Handle{
// imagine some handles to video memory here
Handle(Data d){
// (upload data to video memory)
cout<<"+ Handle"<<endl;
}
~Handle(){
// (deallocate the data from video memory)
cout<<"- Handle"<<endl;
}
};
int main(){
vector<Handle> container;
cout<<"start"<<endl;
for(int i=0; i<4; i++){
container.emplace_back(Data(i));
cout<<endl;
}
cout<<"end"<<endl;
}
我的期望:
start
+ Data
+ Handle
- Data
+ Data
+ Handle
- Data
+ Data
+ Handle
- Data
+ Data
+ Handle
- Data
end
-Handle
-Handle
-Handle
-Handle
我得到了什么:
start
+ Data
+ Handle
- Data
- Data
+ Data
+ Handle
- Data
- Handle
- Data
+ Data
+ Handle
- Data
- Handle
- Handle
- Data
+ Data
+ Handle
- Data
- Data
end
- Handle
- Handle
- Handle
- Handle
任何人都可以解释这种行为吗?
答案 0 :(得分:4)
Handle(Data d)
按值获取Data
个对象,因此Handle构造函数中的d
实际上是传递给Handle构造函数的对象的副本。由于必须创建副本,因此必须销毁副本。它的范围是Handle构造函数的主体,这就是为什么它发生在&#34; + Handle&#34;
这里的构造函数应该是什么样的:
Handle(const Data& d){
// (upload data to video memory)
cout<<"+ Handle"<<endl;
}
const引用是为了防止不必要的复制。
答案 1 :(得分:4)
您对代码的修改可以帮助您更好地了解正在发生的事情。
#include <iostream>
#include <vector>
using namespace std;
struct Data{
int data;
static int allcount;
int count;
Data(int x) : count(allcount) {
data = x;
allcount++;
cout<<"+ Data "<< count <<endl;
}
Data(const Data &d) : count(allcount) {
allcount++;
cout<<"+ Data(copy of " << d.count << ") "<< count <<endl;
}
~Data(){cout<<"- Data "<< count <<endl;}
};
struct Handle{
static int allcount;
int count;
// imagine some handles to video memory here
Handle(Data d) : count(allcount) {
allcount++;
// (upload data to video memory)
cout<<"+ Handle " << count << endl;
}
Handle(const Handle &h) : count(allcount) {
allcount++;
cout<<"+ Handle(copy of " << h.count << ") "<< count <<endl;
}
~Handle(){
// (deallocate the data from video memory)
cout<<"- Handle " << count <<endl;
}
};
int Handle::allcount=0;
int Data::allcount=0;
int main(){
vector<Handle> container;
cout<<"start"<<endl;
for(int i=0; i<4; i++){
container.emplace_back(Data(i));
cout<<endl;
}
cout<<"end"<<endl;
}
它的作用是用一个整数跟踪每个分配和释放,以唯一地标识每个分配和释放。还明确添加了复制构造函数。当我在我的系统上运行时,我得到以下内容:
start
+ Data 0
+ Data(copy of 0) 1
+ Handle 0
- Data 1
- Data 0
+ Data 2
+ Data(copy of 2) 3
+ Handle 1
- Data 3
+ Handle(copy of 0) 2
- Handle 0
- Data 2
+ Data 4
+ Data(copy of 4) 5
+ Handle 3
- Data 5
+ Handle(copy of 2) 4
+ Handle(copy of 1) 5
- Handle 2
- Handle 1
- Data 4
+ Data 6
+ Data(copy of 6) 7
+ Handle 6
- Data 7
- Data 6
end
- Handle 4
- Handle 5
- Handle 3
- Handle 6
如您所见,Handle
被多次复制。这是因为当他们调入的容器调整大小时需要复制它们。如果添加行
container.reserve(4);
就在打印&#34;开始&#34;的行之前,我想你会在第一时间看到你期望看到的内容。也就是说,没有Handle
个副本。