在设计 STL 样式容器时,使用按值传递还是按引用传递赋值运算符更好?

When designing an STL style container is it better to use a pass-by-value or pass-by-reference assignment operator?

提问人:sjrowlinson 提问时间:8/9/2016 最后编辑:sjrowlinson 更新时间:8/9/2016 访问量:78

问:

以下是我一直在编码的 STL 样式容器的最小示例。

dynamic_matrix

template<class _Ty,
    class _Alloc = std::allocator<_Ty>
> class dynamic_matrix {
public:
    // PUBLIC TYPEDEFS
    typedef _Ty value_type;
    typedef _Alloc allocator_type;
    typedef _Ty& reference;
    typedef const _Ty& const_reference;
    typedef std::size_t size_type;
    //... other necessary typedefs...
    // CONSTRUCTION/ASSIGNMENT
    dynamic_matrix() : dynamic_matrix(_Alloc()) {}
    explicit dynamic_matrix(const _Alloc& alloc)
        : mtx(alloc), row_(0), cols_(0) {}
    explicit dynamic_matrix(size_type rows, size_type cols, const _Alloc& alloc = _Alloc())
        : mtx(rows*cols, alloc), rows_(rows), cols_(cols) {}
    dynamic_matrix& operator=(dynamic_matrix _other) {
        if (this != &_other)
            swap(*this, _other);
        return *this;
    }
    // ...
    // MODIFIERS
    void swap(dynamic_matrix& _other) {
        mtx.swap(_other.mtx);
        std::swap(rows_, _other.rows_);
        std::swap(cols_, _other.cols_);
    }
    static void swap(dynamic_matrix& lhs, dynamic_matrix& rhs) {
        lhs.swap(rhs);
    }
private:
    std::vector<value_type, allocator_type> mtx;
    size_type rows_;
    size_type cols_;
};

正如你在上面看到的,我使用的是按值传递的单个值,允许编译器使用复制或移动赋值并应用相关的优化。operator=dynamic_matrix

但是,当我查看典型 STL 容器接口中的赋值运算符(例如 std::vector::operator= 和 std::d eque:operator=)时,它们有两个重载版本 - 一个用于移动,一个用于复制,后者使用传递而不是传递值。const reference

那么,在创建赋值运算符时,我应该使用以下版本来与 STL 样式保持一致,还是坚持按值传递哪个更好?dynamic_matrix

(备选方案):dynamic_matrix::operator=

// copy-assign
dynamic_matrix& operator=(const dynamic_matrix& _other) {
    if (this != &_other)
        dynamic_matrix(_other).swap(*this);
    return *this;
}  
// move-assign
dynamic_matrix& operator=(dynamic_matrix&& _other) {
    if (this != &_other)
        swap(*this, _other);
    return *this;
}

注意:我知道 STL 接口不是容器设计的全部和最终目的,但是如果我正在创建一个尽可能接近 STL 设计的容器,那么坚持标准可能更合适。

C++ STL 赋值运算符

评论

2赞 Baum mit Augen 8/9/2016
_Ty并且是实现保留名称,请勿在用户代码中使用它们。_Alloc
2赞 nate 8/9/2016
请注意:如果按值传递,则此指针不可能与参数地址相同。
0赞 JVApen 8/9/2016
等?为什么要复制和移动而不是只复制?搬家可能比复制便宜,但它不是免费的。
0赞 sjrowlinson 8/9/2016
@BaummitAugen哎呀,没有意识到这一点,以前没有遇到过问题,但我现在会避免它。
4赞 chris 8/9/2016
您可能会对 Scott Meyers 的文章感兴趣,该文章介绍了复制交换成语的几个缺点。在面对决定时,最好牢记一切。

答: 暂无答案