我是否应该用emplace_back替换所有推回的呼叫? 在C++应用程序中,我大量使用STL容器,例如“代码>向量< /代码>。有很多调用push_back,我一直担心不必要的构造和复制操作
我的应用程序非常低级,我非常关心CPU和内存的使用。我是否应该将所有对我是否应该用emplace_back替换所有推回的呼叫? 在C++应用程序中,我大量使用STL容器,例如“代码>向量< /代码>。有很多调用push_back,我一直担心不必要的构造和复制操作,c++,visual-studio,c++11,stl,C++,Visual Studio,C++11,Stl,我的应用程序非常低级,我非常关心CPU和内存的使用。我是否应该将所有对push_back的调用替换为对emplace_back的调用 我正在使用Visual Studio 2013。我将所有对push_back的调用替换为对emplace_back的调用,并注意到以下几点: RAM使用量减少约20%(更新:这可能是由于其他影响) CPU使用率不变 二进制文件稍小(x64) 没有兼容性问题 基于这些经验,如果您的项目不需要向后兼容较旧的编译器,我强烈建议您从push_back移动到emplac
push_back
的调用替换为对emplace_back
的调用
我正在使用Visual Studio 2013。我将所有对
push_back
的调用替换为对emplace_back
的调用,并注意到以下几点:
- RAM使用量减少约20%(更新:这可能是由于其他影响)
- CPU使用率不变
- 二进制文件稍小(x64)
- 没有兼容性问题
基于这些经验,如果您的项目不需要向后兼容较旧的编译器,我强烈建议您从
push_back
移动到emplace_back
。这几乎是一条一贯的规则。您不能依赖复制构造函数的副作用,所以这意味着显式跳过它是正确的做法,但有一种情况
std::vector<std::unique_ptr<A>> foo;
foo.emplace_back( new A );
std::vector foo;
foo.emplace_back(新A);
如果在某个时间触发了抛出,如向量调整大小时,则以泄漏结束。所以不可能把你放回去
如果A
构造函数和您发送的参数是异常安全的,则没有理由不使用emplace\u back。此测试:
#include <type_traits>
#include <typeinfo>
#include <iostream>
#ifndef _MSC_VER
# include <cxxabi.h>
#endif
#include <memory>
#include <string>
#include <cstdlib>
#include <vector>
template <typename T>
std::string
type_name()
{
typedef typename std::remove_reference<T>::type TR;
std::unique_ptr<char, void(*)(void*)> own
(
#ifndef _MSC_VER
abi::__cxa_demangle(typeid(TR).name(), nullptr,
nullptr, nullptr),
#else
nullptr,
#endif
std::free
);
std::string r = own != nullptr ? own.get() : typeid(TR).name();
if (std::is_const<TR>::value)
r += " const";
if (std::is_volatile<TR>::value)
r += " volatile";
if (std::is_lvalue_reference<T>::value)
r += "&";
else if (std::is_rvalue_reference<T>::value)
r += "&&";
return r;
}
template <int N>
struct member
{
member()
{
std::cout << type_name<member>() << "()\n";
}
~member()
{
std::cout << "~" << type_name<member>() << "()\n";
}
member(member const& x)
{
std::cout << type_name<member>()
<< "(" << type_name<decltype(x)>() << ")\n";
}
member& operator=(member const& x)
{
std::cout << type_name<member>() << "::operator=("
<< type_name<decltype(x)>() << ")\n";
return *this;
}
member(member&& x)
{
std::cout << type_name<member>()
<< "(" << type_name<decltype(x)>() << ")\n";
}
member& operator=(member&& x)
{
std::cout << type_name<member>() << "::operator=("
<< type_name<decltype(x)>() << ")\n";
return *this;
}
};
int
main()
{
std::vector<member<1>> v;
v.reserve(10);
member<1> m;
std::cout << "\npush_back an lvalue\n";
v.push_back(m);
std::cout << "\nemplace_back an lvalue\n";
v.emplace_back(m);
std::cout << "\npush_back an xvalue\n";
v.push_back(std::move(m));
std::cout << "\nemplace_back an xvalue\n";
v.emplace_back(std::move(m));
std::cout << "\npush_back a prvalue\n";
v.push_back(member<1>{});
std::cout << "\nemplace_back an prvalue\n";
v.emplace_back(member<1>{});
std::cout << "\nDone\n";
}
#包括
#包括
#包括
#ifndef\u理学硕士
#包括
#恩迪夫
#包括
#包括
#包括
#包括
模板
字符串
键入_name()
{
typedef typename std::remove_reference::type TR;
标准::唯一的
(
#ifndef\u理学硕士
abi::_cxa_demangle(typeid(TR).name(),nullptr,
空PTR,空PTR),
#否则
nullptr,
#恩迪夫
免费
);
std::string r=own!=nullptr?own.get():typeid(TR.name();
if(std::is_const::value)
r+=“常数”;
if(std::is_volatile::value)
r+=“挥发性”;
if(std::is_lvalue_reference::value)
r+=“&”;
else if(std::is\u rvalue\u reference::value)
r+=“&&”;
返回r;
}
模板
结构成员
{
成员()
{
std::cout你如何判断替换一个函数会减少RAM?@Billz,当你的程序使用push_back
时,你测量RAM使用情况,然后用emplace_back
替换它,然后再次测量。@Billz:正如Rob在之前和之后写的那样,测量就是我所做的。这得益于我的应用程序是一个用户体验监控专业软件管道().FWIW,尽管在这种情况下,您应该编写自己的make_unique
函数,将参数转发给std::unique_ptr
构造函数,以避免出现此问题。在Visual Studio中,您必须手动消除一些采用不同参数数的重载,这是一个难题,但值得增加in安全。
member<1>()
push_back an lvalue
member<1>(member<1> const&)
emplace_back an lvalue
member<1>(member<1> const&)
push_back an xvalue
member<1>(member<1>&&)
emplace_back an xvalue
member<1>(member<1>&&)
push_back a prvalue
member<1>()
member<1>(member<1>&&)
~member<1>()
emplace_back an prvalue
member<1>()
member<1>(member<1>&&)
~member<1>()
Done
~member<1>()
~member<1>()
~member<1>()
~member<1>()
~member<1>()
~member<1>()
~member<1>()