1.替换兰特
C ++ 11的一大收获是必须用random标头rand()
中的所有可用选项替换对的使用。在许多情况下,更换应该很简单。rand()
斯蒂芬·拉瓦维(Stephan T.Lavavej)可能以他的演讲rand()被认为有害来表达这一观点。这些示例显示了[0,10]
使用的均匀整数分布rand()
:
#include <cstdlib>
#include <iostream>
#include <ctime>
int main()
{
srand(time(0)) ;
for (int n = 0; n < 10; ++n)
{
std::cout << (rand() / (RAND_MAX / (10 + 1) + 1)) << ", " ;
}
std::cout << std::endl ;
}
并使用std :: uniform_int_distrubution:
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 e2(rd());
std::uniform_int_distribution<> dist(0, 10);
for (int n = 0; n < 10; ++n) {
std::cout << dist(e2) << ", " ;
}
std::cout << std::endl ;
}
与此同时,它应该从std :: random_shuffle移到std :: shuffle,这是由于Deprecate rand和Friends的努力而产生的。SO问题最近解决了这个问题,为什么C ++ 14中不推荐使用std :: shuffle方法?。
注意,不能保证分布在平台之间是一致的。
2.使用std :: to_string代替std :: ostringstream或sprintf
C ++ 11提供 std :: to_string,可用于将数字转换为std :: string,它将产生与等效的std :: sprintf相同的内容。最有可能用它代替std :: ostringstream或snprintf
。这更多的是方便,性能可能不会有太大的区别,并且从C ++中的从快速整数到字符串的转换中可以看出,如果主要关注性能,则可能有更快的替代方法:
#include <iostream>
#include <sstream>
#include <string>
int main()
{
std::ostringstream mystream;
mystream << 100 ;
std::string s = mystream.str();
std::cout << s << std::endl ;
char buff[12] = {0};
sprintf(buff, "%d", 100);
std::string s2( buff ) ;
std::cout << s2 << std::endl ;
std::cout << std::to_string( 100 ) << std::endl ;
}
3.使用constexpr代替模板元编程
如果要处理文字,则可能会在模板元编程上使用constexpr函数,从而产生的代码更清晰,编译速度可能更快。本文想要的速度?使用constexpr元编程!提供了使用模板元编程确定素数的示例:
struct false_type
{
typedef false_type type;
enum { value = 0 };
};
struct true_type
{
typedef true_type type;
enum { value = 1 };
};
template<bool condition, class T, class U>
struct if_
{
typedef U type;
};
template <class T, class U>
struct if_<true, T, U>
{
typedef T type;
};
template<size_t N, size_t c>
struct is_prime_impl
{
typedef typename if_<(c*c > N),
true_type,
typename if_<(N % c == 0),
false_type,
is_prime_impl<N, c+1> >::type >::type type;
enum { value = type::value };
};
template<size_t N>
struct is_prime
{
enum { value = is_prime_impl<N, 2>::type::value };
};
template <>
struct is_prime<0>
{
enum { value = 0 };
};
template <>
struct is_prime<1>
{
enum { value = 0 };
};
并使用constexpr函数:
constexpr bool is_prime_recursive(size_t number, size_t c)
{
return (c*c > number) ? true :
(number % c == 0) ? false :
is_prime_recursive(number, c+1);
}
constexpr bool is_prime_func(size_t number)
{
return (number <= 1) ? false : is_prime_recursive(number, 2);
}
constexpr版本比模板元编程实现要短得多,更易于理解,并且性能要好得多。
4.使用类成员初始化提供默认值
正如最近的内容所述,声明中新的C ++ 11成员初始化功能是否使初始化列表过时了?类成员初始化可用于提供默认值,并可简化类具有多个构造函数的情况。
Bjarne Stroustrup在C ++ 11 FAQ中提供了一个很好的例子,他说:
这节省了一些键入操作,但是真正的好处是具有多个构造函数的类。通常,所有构造函数都为成员使用通用的初始化程序:
并提供了具有常见初始化程序的成员的示例:
class A {
public:
A(): a(7), b(5), hash_algorithm("MD5"), s("Constructor run") {}
A(int a_val) : a(a_val), b(5), hash_algorithm("MD5"), s("Constructor run") {}
A(D d) : a(7), b(g(d)), hash_algorithm("MD5"), s("Constructor run") {}
int a, b;
private:
HashingFunction hash_algorithm;
std::string s;
};
并说:
hash_algorithm和s均具有单个默认值的事实在代码混乱中丢失,并且很容易在维护期间成为问题。相反,我们可以排除数据成员的初始化:
class A {
public:
A(): a(7), b(5) {}
A(int a_val) : a(a_val), b(5) {}
A(D d) : a(7), b(g(d)) {}
int a, b;
private:
HashingFunction hash_algorithm{"MD5"};
std::string s{"Constructor run"};
};
请注意,在C ++ 11中,在类成员初始化器中使用的类是 尽管在C ++ 14中取消了此限制,但不再是聚合。
5.使用cstdint中的固定宽度整数类型代替手动滚动的typedef
由于C ++ 11标准使用C99作为规范性引用,因此我们也获得了固定宽度的整数类型。例如:
int8_t
int16_t
int32_t
int64_t
intptr_t
尽管其中一些是可选的,但对于确切的宽度整数类型,7.18.1.1
适用于C99部分中的以下内容:
这些类型是可选的。但是,如果实现提供的整数类型的宽度为8、16、32或64位,没有填充位,并且(对于带符号类型)具有二进制补码表示,则它应定义相应的typedef名称。