c++ - 返回绑定(bind)的本地函数对象会导致未定义的行为吗?

标签 c++ c++11 undefined-behavior function-object

下面我举个例子。该程序编译并运行良好,但我想知道根据 C++11 标准,这是否是理论上未定义的行为;我可以返回绑定(bind)(临时)局部函数对象的结果吗?

示例代码(经过简短编辑):

#include <iostream>
#include <functional>

struct MyFunctionObject
{
    inline void operator() ( const std::string& name )
        { std::cout<< "Hello " << name << "!" << std::endl; }
};

std::function< void () > my_greeter( const std::string& name )
{
    MyFunctionObject fun;
    return std::bind( fun, name );
}

int main()
{
    auto g = my_greeter("sheljohn");
    g();
}

编辑原始示例:

#include <random>
#include <functional>
#include <algorithm>
#include <utility>
#include <iostream>



        /********************     **********     ********************/
        /********************     **********     ********************/



namespace foo {


/**
 * Type of the generator returned by the method 'bind' below.
 */
template <class _dist>
using generator_type = std::function< typename _dist::result_type () >;

// ------------------------------------------------------------------------

/**
 * Wrapper for C++11 random library.
 */
template <
    class _engine = std::mt19937_64,
    class _device = std::random_device
>
struct random
{
    typedef _engine engine_type;
    typedef _device device_type;
    typedef random<_engine,_device> self;

    template <class _dist>
    static inline generator_type<_dist>
    bind( _dist& distribution )
        { return std::bind( distribution, self::engine ); }

    template <class _dist>
    static inline generator_type<_dist>
    bind( _dist&& distribution )
        { return std::bind( distribution, self::engine ); }

    static engine_type engine;
    static device_type device;
};

// Initialize static engine
template <class _engine,class _device>
_device random<_engine,_device>::device;

template <class _engine,class _device>
_engine random<_engine,_device>::engine = _engine( device() );

// ------------------------------------------------------------------------

/**
 * Generic binder to standard random distributions.
 *
 * SO QUESTION: does this cause undefined behaviour?
 */

template <class _dist, class... Args>
constexpr generator_type<_dist> random_generator( Args&&... args )
    { return random<>::bind( _dist( std::forward<Args>(args)... ) ); }


}; // namespace: foo



        /********************     **********     ********************/
        /********************     **********     ********************/



int main()
{
    auto ngen = foo::random_generator< std::normal_distribution<double> >( 0.0, 1.0 );

    for(unsigned i=0; i<10; ++i) 
        std::cout<< ngen() << " " << std::endl;
}

最佳答案

该标准实际上有一个关于调用 bind() 的特定位使用随机数生成器,在 §26.5 中:

[ Note: These entities are specified in such a way as to permit the binding of any uniform random number generator object e as the argument to any random number distribution object d, thus producing a zero-argument function object such as given by bind(d,e). —end note ]

所以你正在做的事情是明确允许的。

同样来自 [func.bind.bind] ,描述说明当您调用 bind(F&& f, BoundArgs&&... bound_args) 时那(强调我的):

  • FD is the type decay_t<F>,
  • fd is an lvalue of type FD constructed from std::forward<F>(f)
  • Ti is the ith type in the template parameter pack BoundArgs
  • TiD is the type decay_t<Ti>
  • ti is the ith type in the function parameter pack bound_args
  • tid is an lvalue of type TiD constructed from std::forward<Ti>(ti)
  • ..

Returns: A forwarding call wrapper g... The effect of g(,u1, u2, ..., uM) shall be INVOKE(fd, std::forward<V1>(v1), std::forward<V2>(V2), ... std::forward<VN>(vN), result_of_t<FD cv & (V1, V2, ..., VN)>)

这部分让我有点困惑,但基本上你传入的仿函数和参数被转发(复制/移动)到本地版本,fdtid... . bind不会保留对仿函数的引用(FD 不是引用类型!),所有参数也是如此(TiD 类型为 BoundArgs也不是引用类型)。所以在你的新例子中,即使 funname 的字符串是对两者超出范围的引用,bind()结果仍然是一个有效的可调用对象。

这里没有UB。

关于c++ - 返回绑定(bind)的本地函数对象会导致未定义的行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27962421/

相关文章:

c++ - 在qt c++中连续更新一个值

c++ - 无法使用 GCC 5.1 工具链编译 C++11 源代码

c++ - 如何根据空格删除字符串

c++ - 编译器会优化除法成乘法吗

java - Android调试器隐藏局部变量

c++ - 测试未定义的行为

c++ - 如何在 vc++ 中执行从安装目录读取数据的应用程序

c++ - 当我按值传递参数时对象被破坏了?

c语言+二维数组

c++ - 如何使用std::vector <unique_ptr <T >>作为默认参数