Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可以使用C++;11';s';自动';提高绩效?_C++_Performance_C++11_Auto - Fatal编程技术网

C++ 可以使用C++;11';s';自动';提高绩效?

C++ 可以使用C++;11';s';自动';提高绩效?,c++,performance,c++11,auto,C++,Performance,C++11,Auto,我可以理解为什么C++11中的auto类型提高了正确性和可维护性。我已经读到它也可以提高性能(由Herb Sutter编写),但是我错过了一个很好的解释 auto如何提高性能 有人能举个例子吗 因为auto推导初始化表达式的类型,所以不涉及类型转换。与模板算法相结合,这意味着您可以得到比自己创建类型更直接的计算——尤其是在处理无法命名其类型的表达式时 一个典型的例子来自(ab)使用std::function: std::function<bool(T, T)> cmp1 = std

我可以理解为什么C++11中的
auto
类型提高了正确性和可维护性。我已经读到它也可以提高性能(由Herb Sutter编写),但是我错过了一个很好的解释

  • auto
    如何提高性能
  • 有人能举个例子吗

因为
auto
推导初始化表达式的类型,所以不涉及类型转换。与模板算法相结合,这意味着您可以得到比自己创建类型更直接的计算——尤其是在处理无法命名其类型的表达式时

一个典型的例子来自(ab)使用
std::function

std::function<bool(T, T)> cmp1 = std::bind(f, _2, 10, _1);  // bad
auto cmp2 = std::bind(f, _2, 10, _1);                       // good
auto cmp3 = [](T a, T b){ return f(b, 10, a); };            // also good

std::stable_partition(begin(x), end(x), cmp?);

这始终是一个引用,绑定到函数调用表达式的值,并且从不构造任何其他对象。如果您不知道返回值的类型,可能会被迫通过
t&&f=makathing()
之类的方式构造一个新对象(可能是临时对象)。(此外,
auto&&
甚至在返回类型不可移动且返回值为prvalue时工作。)

auto
可以通过避免无提示隐式转换来帮助提高性能。我发现一个引人注目的例子如下

std::map<Key, Val> m;
// ...

for (std::pair<Key, Val> const& item : m) {
    // do stuff
}
类型转换是允许的隐式转换,其原因与您可以将
常量键
转换为
的原因相同,但我们必须构造新类型的临时值才能实现这一点。因此,我们的循环实际上是:

std::pair<Key, Val> __tmp = *iter;       // construct a temporary of the correct type
std::pair<Key, Val> const& item = __tmp; // then, take a reference to it

刚刚为我们保存了大量副本-现在引用的类型与初始值设定项类型匹配,因此不需要临时或转换,我们可以直接引用

有两类

auto
可以避免类型擦除。有不可命名的类型(如lambdas)和几乎不可命名的类型(如
std::bind
或其他类似表达式模板的结果)

如果没有
auto
,您最终必须键入擦除数据的内容,例如
std::function
。类型擦除有成本

std::function<void()> task1 = []{std::cout << "hello";};
auto task2 = []{std::cout << " world\n";};
如果
expression()
返回
Bar const&
Bar
甚至
Bar&
,则将编译,其中
Foo
可以从
Bar
构造。将创建一个临时的
Foo
,然后绑定到
f
,其生存期将延长到
f
消失

程序员可能是指
Bar const&f
,不打算在那里复制,但无论如何都要复制

最常见的例子是
*std::map::const_迭代器
的类型,它是
std::pair const&
而不是
std::pair const&
,但错误是一类以性能为代价的错误。您可以从
std::pair
构造
std::pair
。(地图上的键是const,因为编辑它是个坏主意)


Barry和KerrekSB都在他们的回答中首先阐明了这两个原则。这只是试图在一个答案中突出这两个问题,措辞针对问题,而不是以示例为中心。

现有的三个答案给出了使用
auto
有助于有效“提高性能”的示例

硬币有另一面。对具有不返回基本对象的运算符的对象使用
auto
,可能会导致错误的代码(仍然是可编译和可运行的)。例如,询问如何使用
auto
使用特征库得出不同(不正确)的结果,即以下几行

const auto    resAuto    = Ha + Vector3(0.,0.,j * 2.567);
const Vector3 resVector3 = Ha + Vector3(0.,0.,j * 2.567);

std::cout << "resAuto = " << resAuto <<std::endl;
std::cout << "resVector3 = " << resVector3 <<std::endl;
const auto resAuto=Ha+Vector3(0,0,j*2.567);
常量向量3 resVector3=Ha+Vector3(0,0,j*2.567);

std::看不出哪一个谈论避免意外的隐式转换,例如从小工具到小工具。这不是一个常见的问题。您是否接受“使其不太可能无意中悲观化”作为一种性能改进?仅在将来清理代码的性能,可能是因为我们需要一个简短的答案:不,如果您很好。它可以防止“noobish”错误。C++有一个学习曲线,它会杀死那些根本不做它的人。“巴里,你能解释为什么编译器会很高兴地复制而不是抱怨试图处理<代码> STD::配对const和< /> >作为<代码> STD::配对const和< /Cord>?C++11新手,不确定和
auto
的范围如何发挥作用。@Barry感谢您的解释。这就是我遗漏的部分——出于某种原因,我认为你不可能不断地引用一个临时文件。但是你当然可以——它将在其作用域的末尾不再存在。@barry我明白了,但问题是,没有一个答案能够涵盖使用
auto
来提高性能的所有原因。所以我将用我自己的话写在下面。我仍然不认为这是“
auto
提高性能”的证据。这只是一个例子,“自动<代码>有助于防止程序员错误破坏性能”。我认为,两者之间存在着微妙但重要的区别。不过,+1。这就是使用
auto
的“避免类型擦除”原因。你的另一个变体是“避免意外复制”,但需要修饰;为什么
auto
比在那里简单地键入类型更快?(我认为答案是“你把类型弄错了,它会自动转换”)这使得它成为巴里答案中解释得不太清楚的例子,不是吗?也就是说,有两种基本情况:自动避免类型擦除和自动避免意外转换的静默类型错误,这两种情况都有运行时成本。“不仅调用不能内联”——为什么?您的意思是,如果
std::bind
std::function
std::stabl的相关专业化,原则上有什么东西可以防止调用在数据流分析后被解除虚拟化
std::pair<Key, Val> __tmp = *iter;       // construct a temporary of the correct type
std::pair<Key, Val> const& item = __tmp; // then, take a reference to it
for (auto const& item : m) {
    // do stuff
}
std::function<void()> task1 = []{std::cout << "hello";};
auto task2 = []{std::cout << " world\n";};
Foo const& f = expression();
const auto    resAuto    = Ha + Vector3(0.,0.,j * 2.567);
const Vector3 resVector3 = Ha + Vector3(0.,0.,j * 2.567);

std::cout << "resAuto = " << resAuto <<std::endl;
std::cout << "resVector3 = " << resVector3 <<std::endl;