【问题标题】:Variadic Function That Calls Constructor With Given Arguments使用给定参数调用构造函数的可变参数函数
【发布时间】:2019-07-12 07:03:21
【问题描述】:

需要创建具有不同 arg 类型的可变参数 template<T> 函数,该函数将调用具有给定参数的 T 的构造函数,有点像创建线程但反向(创建线程时,其构造函数在给定函数指针处调用函数)。

所以在伪代码中应该是这样的

template<typename T>
T* CreateNew( ARGS ) {
    return new T( ARGS );    //Constructor Gets Same Arguments That Were 
}                            //Passed To The Function

希望这种行为类似于创建线程时,当他们调用具有不同类型参数的函数时(我不确定如何实现)。

【问题讨论】:

    标签: c++ function templates constructor variadic


    【解决方案1】:

    这对我来说并不完全清楚,但我认为您想查找可变参数模板,例如:

    template <typename T, typename... Args>
    T* CreateNew(Args... args) {
        return new T(args...);
    }
    

    添加示例:

    #include <iostream>
    
    class A {
        public:
        A(int a){
            std::cout<<__PRETTY_FUNCTION__<<std::endl;
        }
        A(std::string a){
            std::cout<<__PRETTY_FUNCTION__<<std::endl;
        }
        A(int a,std::string b){
            std::cout<<__PRETTY_FUNCTION__<<std::endl;
        }
    };
    
    template<typename T, typename... Args>
    T* create(Args... args){
        return new T(args...);
    }
    
    int main(){
        A b(1);
        A c("a");
        A d(1,"a");
        A* bp = create<A>(1);
        A* cp = create<A>("a");
        A* dp = create<A>(1,"a");
        // This code leaks
        return 0;   
    }
    

    请注意,由于更改尽可能少,因此我们仍然在此处返回 T* 作为原始代码。大多数时候,这不是一个好主意,因为所有权是通过原始指针传递的。因此,根据 cmets 的建议,您可能希望使用 std::unique_ptr,这将使您的 CreateNew 函数基本上等同于 std::make_unique

    【讨论】:

    • 进一步阅读:Parameter packs
    • 并且使用std::unique_ptr而不是原始的拥有指针会更好(并且可以避免当前的内存泄漏)。
    • @Jarod42 你说的完全正确,感谢您指出。由于我想尽量减少对 OT 代码的更改,因此我只是在示例中添加了一条注释,并添加了一段关于使用 std::unique_ptrstd::make_unique 的段落。
    • 这个实现被破坏了,因为它不能完美地转发args...
    【解决方案2】:

    这个函数的正确写法是

    template <typename T, typename... Args>
    T* CreateNew(Args&&... args) {
        return new T(std::forward<Args>(args)...);
    }
    

    没有转发引用Args&amp;&amp;和没有std::forward,传递参数的原始值类别将不会传播到T的构造函数,导致潜在的性能和语义问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-05
      • 2012-06-17
      • 2011-10-08
      • 1970-01-01
      • 1970-01-01
      • 2016-01-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多