做你正在寻找的东西并不难:
主文件
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
#include "Point.h"
int main() {
std::random_device rd; // Random Device: Used To Seed Mersenne Random Generator
std::mt19937 gen; // Mersenne Twister
gen.seed( rd() ); // Seed The Generator
std::uniform_int_distribution<> dist(0, 100); // Uniform Int Distribution between [a, max]
// Point<int>
std::vector<Point<int>> points;
points.reserve( NUM_POINTS );
for ( std::size_t i = 0; i < NUM_POINTS; i++ ) {
// Instead of creating a temporary stack copy each iteration
// I chose to use the constructor directly and instead of
// push_back, I'm using emplace_back.
// Point<int> p( dist( gen ), dist( gen ) );
// points.push_back( p );
points.emplace_back( Point<int>( dist( gen ), dist( gen ) ) );
}
std::cout << "Showing 10 points of type int with random (x,y):\n";
for ( auto& p : points ) {
std::cout << p;
}
std::cout << std::endl;
// Point<float>
std::vector<Point<float>> points2;
points.reserve( NUM_POINTS );
std::uniform_real_distribution<float> dist2( 0, 100.0f );
for ( std::size_t i = 0; i < NUM_POINTS; i++ ) {
// Instead of creating a temporary stack copy each iteration
// I chose to use the constructor directly and instead of
// push_back, I'm using emplace_back.
// Point<float> p( dist( gen ), dist( gen ) );
// points2.push_back( p );
points2.emplace_back( Point<float>( dist( gen ), dist( gen ) ) );
}
std::cout << "Showing 10 points of type float with random (x,y):\n";
for ( auto& p : points2 ) {
std::cout << p;
}
std::cout << std::endl;
// Sorting the containers:
std::sort( points.begin(), points.end() );
std::sort( points2.begin(), points2.end() );
std::cout << "Showing the sorted points with type int (x,y):\n";
for ( auto& p : points ) {
std::cout << p;
}
std::cout << std::endl;
std::cout << "Showing the sorted points with type float (x,y):\n";
for ( auto& p : points2 ) {
std::cout << p;
}
std::cout << std::endl;
std::cout << std::endl;
system( "PAUSE" );
return 0;
}
点.h
#ifndef POINT_H
#define POINT_H
#include <iostream>
#include <tuple> // std::tie
const std::size_t NUM_POINTS { 10 };
// Need class Point prototype for operator<< declaration
template<class> class Point;
// Need operator<< declaration for class template Point's friend declaration
template<class T>
std::ostream& operator<<( std::ostream& out, const Point<T>& );
// Class Declaration & Definition
template<class T>
class Point {
public:
T _x;
T _y;
Point() : _x( 0 ), _( 0 ) {}
Point( T x, T y ) : _x( x ), _y( y ) {}
Point( T& x, T& y ) : _x( x ), _y( y ) {}
Point( T* x, T* y ) : _x( *x ), _y( *y ) {}
// friend prototype: notice the extra <> in this declaration
// It tells the compiler that this friend function will be a specialization of this class template
friend std::ostream& operator<< <>( std::ostream& out, const Point<T>& p );
// operator< for comparison
bool operator<( Point<T>& p ) {
// std::tie makes it real easy to compare a (set) of values.
return std::tie( _x, _y ) < std::tie( p._x, p._y );
}
// operator> for comparison
bool operator<( Point<T>& p ) {
return !(*this < p );
}
// operator== for comparison
bool operator==( Point<T>& p ) {
return (this->_x == p._x && this->y == p._y );
}
};
// operator<< definition
template<class T>
std::ostream& operator<<( std::ostream& out, const Point<T>& p ) {
return out << "(" << p._x << "," << p._y << ")\n";
}
#endif // !POINT_H
至于类的实现template Point<T>
可以参考头文件中的注释。
对于主要功能的细节,我将介绍其中的一些细节。
为了生成您的随机值,我强烈建议您远离random()
或与其相关的任何已弃用或即将成为功能的功能。我将首先学习和使用可以在标准库中找到的伪随机生成器以及不同类型的分布:这些都可以在<random>
头文件中找到。您可以使用std::default_random_engine()
,但我更喜欢使用std::random_device
我们可以将其用于SEED
我们选择的引擎(发电机)。最常用的引擎或生成器之一被称为Mersenne Twister
which is std::mt19937
,并且它也有 65 位版本。这很简单。
{
std::random_device rd; // create an instance of our device to seed with
std::mt19937 gen; // create an instance of our generator (engine)
gen.seed( rd() ); // This seeds the generator (engine)
// Now we need a distribution along with its data type
// there are different versions of these distributions for different types
// Some are for integral types while others are for floating point types
// Here we want a uniform distribution for int so we default the template
std::uniform_int_distribution<> dist(0, 100); //random from [0,100]
// otherwise we could of done
std::uniform_int_distribution<unsigned int> dist2( 0, 50 ); // random from [0, 50]
// There are other types of distributions
std::normal_distribution<> a;
std::poisson_distribution<> b;
// etc.
// If the distributions say "real" they are floating point types
std::uniform_real_distribution<float> f;
std::uniform_real_distribution<double> d;
// Just as there are different distributions there also other
// generators or engines beside the mersenne twister.
// There is another way besides using `random_device` to seed the generator
// you can use <chrono> header to use `std::chrono::high_resolution_clock
// to seed the generator
// You can also seed by const value
// and you can use std::seed_seq;
}
您可以从此网页找到执行 Pseudo Random Generators & Distributions 所需的所有信息。
所以现在我们已经启动了随机生成器并开始工作,下一步是我们声明 astd::vector<Point<int>>
然后我们使用它的reserve
函数并用我们的 const 设置它NUM_POINTS
。然后我们通过一个 for 循环进行迭代,并用一组随机值NUM_POINTS
填充我们的容器。(x,y)
然后我们使用范围基础 for 循环显示结果。
我重复上述过程以显示它是用浮点数完成的。我这样做是为了展示模板的有用性。
之后,我最终通过std::sort( begin, end )
使用向量的迭代器调用来对容器进行排序。然后我返回并使用范围基数 for 循环来显示两个已排序的向量。
使用 std::sort 很容易,因为我们operator<()
为我们的类定义了一个重载并且我们使用 std::tie 来轻松地比较它们。通过将一堆零件(例如乐高积木)组合在一起,这向您展示了标准库的力量!