想在代码里通过嵌套类作为迭代器,访问外层类的数据。
主要是为了避免在头文件中包含STL头文件,编译时间伤不起
然后出现了神奇的bug,简化后代码如下:
class A {
public:
class B {
public:
explicit B(void):idx(3){}
B(const B&b) {
idx = 4; // 不被调用
}
private:
int idx=0;
};
B getB()
{ return A::B(); }
};
void test2(){
A a;
A::B b = a.getB(); // b.idx 最终的值为 3
}
百思不得其解,google很久,最后得知c++11起添加了move
操作避免复制临时对象和右值优化,c++17更是添加了Copy Elision
- 临时对象优化(RVO, Returned Value Optimized)分两种,都需要满足临时对象和同类型变量赋值条件:
- 无名返回值优化(URVO, Unamed Returned Value Optimized) ,像代码中的
A::getB()
- 具名返回值优化(NRVO, UnamedReturned Value Optimized),类似于URVO,像
A::getB(){B c; return c;}
- 无名返回值优化(URVO, Unamed Returned Value Optimized) ,像代码中的
- 右值拷贝优化,临时对象被赋值给同类型对象时。
还是以代码举例
class A {
public:
class B {
public:
explicit B(void):idx(3){}
B(const B&b)
{ cout<<"copy"<<move; }
B(const B&&b) // C++11添加的移动构造函数,配对是的移动赋值函数
{ cout<<"move"<<move; }
private:
int idx=0;
};
B getB()
{ return A::B(); }
B getB2()
{ A::B c; return c; }
};
void test2(){
A a;
A::B b = a.getB(); // 直接移动,**不调用复制,也不调用移动**
A::B b = a.getB2(); // 调用移动构造函数
}
总结:
- 如果嵌套类对象可以有副本且包含指针变量,那么一定要使用共享型指针,如
std::shared_ptr
,不要用std::unique_str
等 - 本贴没有体现,直接说结论,嵌套类需要在dll外使用时,也要像正常类一样dllexport