在 C++11 中不推荐使用哪些 C++ 习语?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9299101/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Which C++ idioms are deprecated in C++11?
提问by Alan Baljeu
With the new standard, there are new ways of doing things, and many are nicer than the old ways, but the old way is still fine. It's also clear that the new standard doesn't officially deprecate very much, for backward compatibility reasons. So the question that remains is:
有了新标准,就有了新的做事方式,很多都比旧的方式更好,但旧的方式还是可以的。同样很明显,出于向后兼容性的原因,新标准并没有正式弃用。所以剩下的问题是:
What old ways of coding are definitely inferior to C++11 styles, and what can we now do instead?
哪些旧的编码方式绝对不如 C++11 风格,我们现在可以做些什么呢?
In answering this, you may skip the obvious things like "use auto variables".
在回答这个问题时,您可以跳过诸如“使用自动变量”之类的明显内容。
采纳答案by Sumant
- Final Class: C++11 provides the
final
specifier to prevent class derivation - C++11 lambdas substantially reduce the need for named function object (functor) classes.
- Move Constructor: The magical ways in which
std::auto_ptr
works are no longer needed due to first-class support for rvalue references. - Safe bool: This was mentioned earlier. Explicit operators of C++11 obviate this very common C++03 idiom.
- Shrink-to-fit: Many C++11 STL containers provide a
shrink_to_fit()
member function, which should eliminate the need swapping with a temporary. - Temporary Base Class: Some old C++ libraries use this rather complex idiom. With move semantics it's no longer needed.
- Type Safe EnumEnumerations are very safe in C++11.
- Prohibiting heap allocation: The
= delete
syntax is a much more direct way of saying that a particular functionality is explicitly denied. This is applicable to preventing heap allocation (i.e.,=delete
for memberoperator new
), preventing copies, assignment, etc. - Templated typedef: Alias templatesin C++11 reduce the need for simple templated typedefs. However, complex type generators still need meta functions.
- Some numerical compile-time computations, such as Fibonacci can be easily replaced using generalized constant expressions
result_of
: Uses of class templateresult_of
should be replaced withdecltype
. I thinkresult_of
usesdecltype
when it is available.- In-class member initializerssave typing for default initialization of non-static members with default values.
- In new C++11 code
NULL
should be redefined asnullptr
, but see STL's talkto learn why they decided against it. - Expression templatefanatics are delighted to have the trailing return typefunction syntax in C++11. No more 30-line long return types!
- Final Class: C++11 提供了
final
防止类派生的说明符 - C++11 lambda 大大减少了对命名函数对象(函子)类的需求。
- 移动构造函数:
std::auto_ptr
由于对右值引用的一流支持,不再需要神奇的工作方式。 - Safe bool:这在前面提到过。C++11 的显式运算符消除了这个非常常见的 C++03 习语。
- Shrink-to-fit:许多 C++11 STL 容器提供了一个
shrink_to_fit()
成员函数,这应该消除了与临时交换的需要。 - 临时基类:一些旧的 C++ 库使用这个相当复杂的习惯用法。使用移动语义不再需要它。
- 类型安全枚举枚举在 C++11 中非常安全。
- 禁止堆分配:该
= delete
语法是明确拒绝特定功能的一种更直接的方式。这适用于防止堆分配(即=delete
对于成员operator new
)、防止复制、分配等。 - 模板化 typedef:C++11 中的别名模板减少了对简单模板化 typedef 的需求。然而,复杂类型生成器仍然需要元函数。
- 一些数值编译时计算,例如斐波那契,可以使用广义常量表达式轻松替换
result_of
:类模板的使用result_of
应替换为decltype
. 我想result_of
使用decltype
时,可用它。- 类内成员初始值设定项为具有默认值的非静态成员的默认初始化保存键入。
- 在新的 C++11 中,代码
NULL
应该被重新定义为nullptr
,但请参阅STL 的演讲以了解他们为什么决定反对它。 - 表达式模板狂热者很高兴在 C++11 中有尾随返回类型函数语法。没有更多的 30 行长返回类型!
I think I'll stop there!
我想我会停在那里!
回答by Howard Hinnant
At one point in time it was argued that one should return by const
value instead of just by value:
在某个时间点,有人认为应该按const
值返回而不是仅按值返回:
const A foo();
^^^^^
This was mostly harmless in C++98/03, and may have even caught a few bugs that looked like:
这在 C++98/03 中基本上是无害的,甚至可能发现了一些类似的错误:
foo() = a;
But returning by const
is contraindicated in C++11 because it inhibits move semantics:
但是返回 byconst
在 C++11 中是禁忌的,因为它禁止移动语义:
A a = foo(); // foo will copy into a instead of move into it
So just relax and code:
所以只需放松和编码:
A foo(); // return by non-const value
回答by Howard Hinnant
As soon as you can abandon 0
and NULL
in favor of nullptr
, do so!
一旦你可以放弃0
和NULL
支持nullptr
,就去做吧!
In non-generic code the use of 0
or NULL
is not such a big deal. But as soon as you start passing around null pointer constants in generic code the situation quickly changes. When you pass 0
to a template<class T> func(T)
T
gets deduced as an int
and not as a null pointer constant. And it can not be converted back to a null pointer constant after that. This cascades into a quagmire of problems that simply do not exist if the universe used only nullptr
.
在非通用代码中,使用0
orNULL
不是什么大问题。但是一旦您开始在通用代码中传递空指针常量,情况就会迅速改变。当您传递0
给 atemplate<class T> func(T)
T
时,它被推导出为 anint
而不是空指针常量。并且在那之后它不能转换回空指针常量。这会导致一系列问题,如果仅使用宇宙,这些问题根本就不存在nullptr
。
C++11 does not deprecate 0
and NULL
as null pointer constants. But you should code as if it did.
C++11 不弃用0
并NULL
作为空指针常量。但是你应该像它那样编码。
回答by kennytm
Safe bool idiom→ explicit operator bool()
.
安全布尔习语→ explicit operator bool()
.
Private copy constructors (boost::noncopyable) → X(const X&) = delete
私有复制构造函数 (boost::noncopyable) → X(const X&) = delete
Simulating final class with private destructor and virtual inheritance→ class X final
使用私有析构函数和虚拟继承模拟最终类→class X final
回答by Klaim
One of the things that just make you avoid writing basic algorithms in C++11 is the availability of lambdas in combination with the algorithms provided by the standard library.
使您避免在 C++11 中编写基本算法的一件事是 lambda 与标准库提供的算法相结合的可用性。
I'm using those now and it's incredible how often you just tell what you want to do by using count_if(), for_each() or other algorithms instead of having to write the damn loops again.
我现在正在使用它们,令人难以置信的是,您只需使用 count_if()、for_each() 或其他算法来告诉您想要做什么,而不必再次编写该死的循环。
Once you're using a C++11 compiler with a complete C++11 standard library, you have no good excuse anymore to not use standard algorithms to build your's. Lambda just kill it.
一旦您使用带有完整 C++11 标准库的 C++11 编译器,您就再也没有理由不使用标准算法来构建您的. Lambda 只是杀死它。
Why?
为什么?
In practice (after having used this way of writing algorithms myself) it feels far easier to read something that is built with straightforward words meaning what is done than with some loops that you have to uncrypt to know the meaning. That said, making lambda arguments automatically deduced would help a lot making the syntax more easily comparable to a raw loop.
在实践中(在我自己使用过这种编写算法的方式之后),阅读一些用简单的词来表示所做的事情比阅读一些你必须解密才能知道含义的循环要容易得多。也就是说,使 lambda 参数自动推导出将有助于使语法更容易与原始循环进行比较。
Basically, reading algorithms made with standard algorithms are far easier as words hiding the implementation details of the loops.
基本上,阅读用标准算法制作的算法要容易得多,因为文字隐藏了循环的实现细节。
I'm guessing only higher level algorithms have to be thought about now that we have lower level algorithms to build on.
我猜现在我们只需要考虑更高级别的算法,因为我们有较低级别的算法可以构建。
回答by Philipp
You'll need to implement custom versions of swap
less often. In C++03, an efficient non-throwing swap
is often necessary to avoid costly and throwing copies, and since std::swap
uses two copies, swap
often has to be customized. In C++, std::swap
uses move
, and so the focus shifts on implementing efficient and non-throwing move constructors and move assignment operators. Since for these the default is often just fine, this will be much less work than in C++03.
您需要swap
较少地实现自定义版本。在 C++03 中,高效的非抛出swap
通常是必要的,以避免代价高昂的抛出副本,并且由于std::swap
使用了两个副本,因此swap
通常必须进行自定义。在 C++ 中,std::swap
使用move
, 因此重点转移到实现高效且非抛出的移动构造函数和移动赋值运算符上。因为对于这些默认值通常很好,这将比 C++03 中的工作少得多。
Generally it's hard to predict which idioms will be used since they are created through experience. We can expect an "Effective C++11" maybe next year, and a "C++11 Coding Standards" only in three years because the necessary experience isn't there yet.
通常很难预测将使用哪些习语,因为它们是通过经验创造的。我们可以期待“Effective C++11”可能在明年,而“C++11 Coding Standards”仅在三年内出现,因为还没有必要的经验。
回答by Andrzej
I do not know the name for it, but C++03 code often used the following construct as a replacement for missing move assignment:
我不知道它的名字,但 C++03 代码经常使用以下结构来代替缺少的移动分配:
std::map<Big, Bigger> createBigMap(); // returns by value
void example ()
{
std::map<Big, Bigger> map;
// ... some code using map
createBigMap().swap(map); // cheap swap
}
This avoided any copying due to copy elision combined with the swap
above.
这避免了由于复制省略与swap
上述相结合而导致的任何复制。
回答by v010dya
When I noticed that a compiler using the C++11 standard no longer faults the following code:
当我注意到使用 C++11 标准的编译器不再出现以下代码错误时:
std::vector<std::vector<int>> a;
for supposedly containing operator>>, I began to dance. In the earlier versions one would have to do
对于据称包含操作符>>,我开始跳舞。在较早的版本中,您必须这样做
std::vector<std::vector<int> > a;
To make matters worse, if you ever had to debug this, you know how horrendous are the error messages that come out of this.
更糟糕的是,如果你曾经调试过它,你就会知道由此产生的错误消息是多么可怕。
I, however, do not know if this was "obvious" to you.
但是,我不知道这对您来说是否“显而易见”。
回答by Martin A
Return by value is no longer a problem. With move semantics and/or return value optimization (compiler dependent) coding functions are more natural with no overhead or cost (most of the time).
按值返回不再是问题。通过移动语义和/或返回值优化(依赖于编译器),编码功能更自然,没有开销或成本(大多数情况下)。