在c++中将临时插入向量
Pushing temporary into vector in c++
假设启用了正常的编译器优化,以下中发生/存在多少个副本:
std::vector<MyClass> v;
v.push_back(MyClass());
如果不是1个对象创建和0个复制,我能做些什么(包括MyClass
中的更改)来实现这一点,因为在我看来,这才是真正必要的?
如果MyClass
的构造函数有副作用,那么在C++03中不允许消除副本。这是因为作为副本源的临时对象已绑定到引用(push_back
的参数)。
如果MyClass
的复制构造函数没有副作用,则允许编译器根据"好像"规则对其进行优化。我认为,要确定它是否真的使用了"正常优化",唯一明智的方法就是检查发出的代码。不同的人对什么是正常有不同的想法,给定的编译器可能对MyClass
的细节很敏感。我的猜测是,这意味着编译器(或链接器)是否内联了所有可见的内容。如果它做到了,那么它可能会优化,如果它没有,那么它就不会。因此,即使是构造函数代码的大小也可能是相关的,别管它做什么。
因此,我认为您可以做的主要事情是确保MyClass
的默认构造函数和复制构造函数都没有副作用,并且可以内联。如果它们不可用,那么编译器当然会认为它们可能有副作用,并进行复制。如果链接时间优化对您来说是一个正常的编译器选项,那么您不必做太多工作来使它们可用。否则,如果它们是用户定义的,则在定义MyClass
的头文件中执行此操作。默认构造函数可能会产生某些副作用:如果效果不取决于临时的地址与向量元素的地址不同,那么"好像"仍然适用。
在C++11中,您有一个移动(如果它有副作用,也不能忽略它),但您可以使用v.emplace_back()
来避免这种情况。move会调用MyClass
的move构造函数(如果它有),否则会调用copy构造函数,我上面所说的"好像"都适用于moves。emplace_back()
调用无参数构造函数来构造矢量元素(或者,如果您将参数传递给emplace_back
,那么无论哪个构造函数都匹配这些参数),我认为这正是您想要的。
您的意思是:
std::vector<MyClass> v;
v.push_back(MyClass());
无。临时将导致调用push_back的移动版本。即使是搬迁施工也很可能被取消。
如果您有C++11编译器,您可以使用template_back在向量末尾构造元素,无需任何副本。
在C++03中,您将拥有一个构造和一个副本,以及临时的销毁。
如果您的编译器支持C++11,并且MyClass定义了一个移动构造函数,那么您就有一个构造和一个移动。
正如Timbo所提到的,您也可以使用template_back来避免移动,即在原地构建对象。
- 如何在向量数组中插入元素?
- 插入向量时,使用lambda的返回而不是函数的返回是否有意义?
- 在每个偶数特定数字之后,插入向量中
- 插入向量后,删除对WSTRING的引用
- 将唯一的_ptr插入向量为一对
- 计算元素插入向量的次数
- 在c++中将临时插入向量
- 在队列中插入向量元素
- 如何在不使用循环的情况下插入向量
- 将元素插入向量并替换所有其他元素的函数,从而截断最终元素
- 默认插入向量不是默认初始化吗?
- C++不会根据需要将数字/数字插入向量
- 将列表元素插入向量,C++获取其他不需要的值
- 通过在插入点"replacing"迭代器来插入C++向量(有并发症)
- 如何将重复元素插入向量
- 在运行递归函数时将新元素插入向量时出现问题
- 将字符串中的每个单词插入向量中,并计算每个单词的出现次数
- 插入向量时的 C++ 临时对象
- 按字母顺序插入向量
- 使用 std::copy 将元素插入向量