C++ 如何在向量列表初始化时避免对象复制以及如何延长临时

C++ 如何在向量列表初始化时避免对象复制以及如何延长临时,c++,c++11,constructor,C++,C++11,Constructor,考虑下面的代码,其中“MyType”类中的许多对象存储在一个向量中,然后该向量被传递给“VectorProcessor”类的对象: 如果我启用“测试B”,程序输出为: MyType构造函数;x=1 MyType构造函数;x=2 MyType构造函数;x=3 MyType构造函数;x=4 MyType构造函数;x=5 MyType复制构造函数;x=x'+10=11 MyType复制构造函数;x=x'+10=12 MyType复制构造函数;x=x'+10=13 MyType复制构造函数;x=x'+1

考虑下面的代码,其中“MyType”类中的许多对象存储在一个向量中,然后该向量被传递给“VectorProcessor”类的对象:

如果我启用“测试B”,程序输出为:

MyType构造函数;x=1
MyType构造函数;x=2
MyType构造函数;x=3
MyType构造函数;x=4
MyType构造函数;x=5
MyType复制构造函数;x=x'+10=11
MyType复制构造函数;x=x'+10=12
MyType复制构造函数;x=x'+10=13
MyType复制构造函数;x=x'+10=14
MyType复制构造函数;x=x'+10=15
向量值构造函数
MyType析构函数;x=11
MyType析构函数;x=12
MyType析构函数;x=13
MyType析构函数;x=14
MyType析构函数;x=15
MyType析构函数;x=5
MyType析构函数;x=4
MyType析构函数;x=3
MyType析构函数;x=2
MyType析构函数;x=1
r、 getLast():0
然后我问:如果不使用指针或智能指针

1) 如何避免在MyType类的对象中额外复制该occours(对于测试A和B)?
2) 在“测试B”中,为什么在r.getLast()之前调用MyType析构函数?换句话说,如何将临时
向量{1,2,3,4,5}
的寿命延长到块的末尾?

按照
std::initializer\u list
的设计方式,初始化器等效于:

vector<MyType> v{ MyType(1), MyType(2), MyType(3), MyType(4), MyType(5) };
有多种方式可以包装此代码,但这是基本思想



对于第二个问题,临时对象仅在创建它们的完整表达式结束之前有效,少数例外情况除外。绑定到构造函数引用参数不是例外情况之一。您在
测试(A)
中使用的代码是正确的方法。

按照
std::initializer\u list
的设计方法,initializer等效于:

vector<MyType> v{ MyType(1), MyType(2), MyType(3), MyType(4), MyType(5) };
有多种方式可以包装此代码,但这是基本思想



对于第二个问题,临时对象仅在创建它们的完整表达式结束之前有效,少数例外情况除外。绑定到构造函数引用参数不是例外情况之一。您在
测试(A)
中使用的代码是正确的方法。

您编写的
=copy constructor
,实际上是复制赋值运算符(它不是构造函数)。类似于move assignment运算符,从一个更具见解的角度来看:如果不是您有意在各种构造函数中注入副作用,编译器很可能能够优化掉调用move构造函数所产生的额外成本,因此,区别可能没有你想象的那么重要。这个问题有点落后——一个更相关的问题通常是如何避免创建临时变量(或允许/强制编译器省略它们)。一般来说,在语句中创建的未命名临时对象(例如,在您的案例B中,用于构造
r
)只存在到语句结束。根据上下文,延长临时对象寿命的一种方法是给它起一个名称(例如,初始化一个
const
引用以引用它),这样当引用在范围内时,对象将持续。但是,在编写
=copy constructor
的封闭作用域结束之前,无法延长未命名临时对象的生存期,该作用域实际上是复制赋值运算符(它不是构造函数)。类似于move assignment运算符,从一个更具见解的角度来看:如果不是您有意在各种构造函数中注入副作用,编译器很可能能够优化掉调用move构造函数所产生的额外成本,因此,区别可能没有你想象的那么重要。这个问题有点落后——一个更相关的问题通常是如何避免创建临时变量(或允许/强制编译器省略它们)。一般来说,在语句中创建的未命名临时对象(例如,在您的案例B中,用于构造
r
)只存在到语句结束。根据上下文,延长临时对象寿命的一种方法是给它起一个名称(例如,初始化一个
const
引用以引用它),这样当引用在范围内时,对象将持续。但是,在封闭范围结束之前,无法延长未命名临时对象的生命“绑定到构造函数引用参数不是例外情况之一”:您可以再解释一下吗?例外情况是什么(如何延长临时的生存期?@Berk7871“绑定到构造函数引用参数不是例外情况之一):您可以再解释一下吗?例外情况是什么(如何延长临时的生存期?@Berk7871
vector<MyType> v;
v.reserve(5);
for (int i = 1; i <= 5; ++i)
    v.emplace_back(i);