模板 Class 以不同方式实现 Variadic Constructor:每个版本的优缺点是什么?

Template Class With Variadic Constructor implemented in different ways: What are the benefits and downfalls of each version?

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

可变版本:

#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

An object of type std::initializer_list<T> is a lightweight proxy object that provides access to an array of objects of type const T

无法对存储的对象数组进行可变访问。