return时发生了啥
c++小白,谈谈看法,大神绕道
说起来,之前c++primer就有提及,return时会发生拷贝初始化。今天上课看书的时候突然想到,如果代码像下面这样:
1 #include <iostream> 2 3 using namespace std; 4 5 typedef struct xixi x; 6 struct xixi { 7 int xi; 8 xixi(int i) { cout << "默认" << endl; } 9 xixi(const x& n) { cout << "拷贝构造" << endl; } 10 xixi& operator=(const x& n) { 11 cout << "赋值" << endl; 12 return *this; 13 } 14 xixi& operator=(x&& n) { 15 xi = std::move(n.xi); 16 cout << "移动赋值" << endl; 17 return *this; 18 } 19 xixi(x&& n) :xi(std::move(n.xi)){ cout << "移动构造" << endl; } 20 }; 21 22 x f() { 23 x tmp(0); 24 return tmp; 25 } 26 27 int main(void) { 28 x t(1); 29 t = f(); 30 return 0; 31 }
各位看官先看main函数里,我纠结的是,如果没有把调用结果赋值给t,还会发生拷贝初始化吗,答案是会。没有赋值语句时,代码运行结果:
在f()前加入"t="时,如下:
也就是说,有没有赋值语句并不会影响return语句执行拷贝初始化,由于return一个临时对象,且提供了移动构造函数,拷贝初始化选择了移动构造,当没有提供构造函数时,退而求其次,选择拷贝构造函数。把调用结果赋值给t时,同理,有移动赋值就移动赋值,否则拷贝赋值,从而减少开销。
然后我还想说说--
1 typedef struct node node; 2 struct node { 3 node(const node&) { cout << "拷贝" << endl; } 4 //node(node&&) { cout << "移动" << endl; } 5 node() { cout << "默认" << endl; } 6 int xi; 7 }; 8 9 int main(void) { 10 //binaryTree<int> xi; 11 int a[10] = { 6,5,2,5,7,8 }; 12 vector<node> hhh; 13 for (int i = 0;i < 6;i++) { 14 node tmp; 15 hhh.push_back(tmp); 16 } 17 //for (int i = 0;i < 6;i++)xi.insert(&hhh[i]); 18 //xi.inorder(); 19 return 0; 20 }
run一把是这样
???
一开始黑人问号,后来想到vector管理内存是不够就继续申请,所以在我的电脑上vs15在前几个push_back都是一次申请一个node大小的内存,直到倒数第二个才申请了大于或等压两个node的内存,当为node实现移动构造函数时,
会用移动构造函数去代替vector从旧内存到新内存的“搬运”工作,如果实现自己的类时尽量实现移动构造函数,从而减少拷贝的开销,特别是用到stl容器时。
这是今天的一点收获,说起来,其实很多小知识点都在书里看过,但碰到问题时还是没早点能想到原来是这样,实践啊实践出真知。继续前进吧(晚安嘻嘻