我一直在学习C ++ 11到Bjarne Stroustrup的“C ++之旅”。
我有以下代码片段
#include <random>
#include <functional>
int main(int argc, char *argv[])
{
using namespace std;
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution {1,6};
distribution(generator); //Case 1 works
auto die = bind(uniform_int_distribution<>{1,6},default_random_engine{}); //Case 2 works
distribution(std::default_random_engine{}); //Case 3 Compiler error
}
案例3是我自己的创作,而案例2来自书籍,案例1来自其他地方。 为什么案例3会产生下面的编译器错误? 据我所知,案例1和案例3之间的唯一区别是我正在使用std :: default_random_engine的临时实例,这个临时实例似乎适用于案例2 我错过了什么?
错误输出:
random.cpp: In function ‘int main(int, char**)’:
random.cpp:13:46: error: no match for call to ‘(std::uniform_int_distribution<int>) (std::default_random_engine)’
distribution(std::default_random_engine{}); //Case 3 Compiler error
^
In file included from /usr/include/c++/6.3.1/bits/random.h:35:0,
from /usr/include/c++/6.3.1/random:49,
from random.cpp:1:
/usr/include/c++/6.3.1/bits/uniform_int_dist.h:164:2: note: candidate: std::uniform_int_distribution<_IntType>::result_type std::uniform_int_distribution<_IntType>::operator()(_UniformRandomNumberGenerator&) [with _UniformRandomNumberGenerator = std::linear_congruential_engine<long unsigned int, 16807ul, 0ul, 2147483647ul>; _IntType = int; std::uniform_int_distribution<_IntType>::result_type = int] <near match>
operator()(_UniformRandomNumberGenerator& __urng)
^~~~~~~~
/usr/include/c++/6.3.1/bits/uniform_int_dist.h:164:2: note: conversion of argument 1 would be ill-formed:
random.cpp:13:23: error: invalid initialization of non-const reference of type ‘std::linear_congruential_engine<long unsigned int, 16807ul, 0ul, 2147483647ul>&’ from an rvalue of type ‘std::default_random_engine {aka std::linear_congruential_engine<long unsigned int, 16807ul, 0ul, 2147483647ul>}’
distribution(std::default_random_engine{}); //Case 3 Compiler error
^~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/6.3.1/bits/random.h:35:0,
from /usr/include/c++/6.3.1/random:49,
from random.cpp:1:
/usr/include/c++/6.3.1/bits/uniform_int_dist.h:169:2: note: candidate: template<class _UniformRandomNumberGenerator> std::uniform_int_distribution<_IntType>::result_type std::uniform_int_distribution<_IntType>::operator()(_UniformRandomNumberGenerator&, const std::uniform_int_distribution<_IntType>::param_type&) [with _UniformRandomNumberGenerator = _UniformRandomNumberGenerator; _IntType = int]
operator()(_UniformRandomNumberGenerator& __urng,
^~~~~~~~
/usr/include/c++/6.3.1/bits/uniform_int_dist.h:169:2: note: template argument deduction/substitution failed:
random.cpp:13:46: note: candidate expects 2 arguments, 1 provided
distribution(std::default_random_engine{}); //Case 3 Compiler error
^
答案 0 :(得分:2)
distribution(generator);
distribution
修改generator
的状态,并提取值。在下一个调用中,它使用相同的generator
auto die = bind(uniform_int_distribution<>{1,6},default_random_engine{});
在这里,我们将uniform_int_distribution<>{1,6}
和default_random_engine{}
复制到绑定函数对象中。在()
,default_random_engine{}
通过uniform_int_distribution<>{1,6}
将operator()
传递给uniform_int_distribution<>{1,6}
。 default_random_engine{}
修改distribution(std::default_random_engine{});
的状态,在下一次调用时,它返回一个不同的值,因为它使用(现在已修改的)生成器。
random_engine&
在这里,您尝试将distribution
绑定到临时对象。 template<class T>
T& as_lvalue(T&& t){ return t; }
想要修改随机引擎的状态,这就是引用它的原因。
通过临时传递,任何此类更改都将立即丢弃。很容易这样做并搞砸了,所以C ++默认情况下不允许你将临时对象绑定到非const左值引用。
C ++ std的设计者想要这个错误,所以他们通过非const左值引用进行分发。它试图告诉你“这是一个糟糕的计划”。
你可以解决它:
distribution(as_lvalue(std::default_random_engine{}));
现在
default_random_engine
愚弄编译器认为传入的Content-Type: application/json
不是是临时的。它仍然在线的末端消失,并且由分布仔细完成的对发生器状态的修改被丢弃。
在生成伪随机对象时,这通常是不,这就是C ++ 11的随机引擎。
简而言之,不允许将临时值绑定到非常量左值引用。当你这样做时,这是一个错误。如果您有一个既要读取又要写入的参数,并且写入的值很重要,那么它将被非常量左值引用占用,以便阻止您随意传入一个临时的,写入的数据丢失了。
发电机是有状态的。你想保留一个并重复应用它。