以不同方式实现可变参数构造函数的模板类:每个版本的优点和缺点是什么



我用两种不同的方式编写了这个模板类:一种使用可变参数构造函数,另一种使用std::initializer_list<T>。出于这个问题的目的,我将以不同的方式命名类,但请注意,在我的项目中,它是同一个类,因为两个版本都做同样的事情。我想知道这两个版本的好处和缺点是什么。哪一个更有效,为什么?

可变参数版本:

#include <vector>
#include <memory>
template<typename T>
class Nodes {
private:
    unsigned m_numParams;
    std::vector<std::shared_ptr<T>> m_vNodes;
public:
    Nodes() : m_numParams(0), m_vNodes { nullptr } {}
    template <typename ... Ts >
    explicit Nodes( Ts&&...ts ) :
        m_numParams( sizeof...(Ts) ),
        m_vNodes{ std::make_shared<T>( std::forward<Ts>( ts ) )... }
    {}    
}; // Nodes
int main() {
     int x = 3;
     int y = 5;
     int z = 7;
     Nodes<int> nodes( x, y, z );
     return 0;
}

std::initializer_list<T>版本

#include <vector>
#include <memory>
template<typename T>
class Nodes2 {
private:
    unsigned m_numParams;
    std::vector<std::shared_ptr<T>> m_vNodes;
public:
    Nodes2() : m_numParams(0), m_vNodes{ nullptr } {}
    explicit Nodes2( std::initializer_list<T> ini ) :
        m_numParams( ini.size() ) {
        for ( auto&& e : ini ) {
            m_vNodes.push_back( std::make_shared<T>( e ) );
        }
    }
}; // Nodes2
int main() {
    int x = 3;
    int y = 3;
    int z = 3;
    std::initialize_list<int> ini{ x, y, z };
    Nodes2<int> nodes2( ini );
    return 0;    
}

如果您正在创建一个通用容器,并且不知道将要存储的对象类型(T(,并且您希望允许移动构造,那么可变参数版本更好。

这是因为您无法从std::initializer_list移动,因此您的第二个版本必须复制构造T对象。

cppreference

std::initializer_list<T> 类型的对象是一个轻型代理对象,它提供对类型为 const T 的对象数组的访问

无法获得对存储的对象数组的可变访问。

最新更新