过载运算符+ for vector:namespace std

问题描述 投票:0回答:5

我试图重载运算符+和+ = std :: vector,我做的是

namespace std {
    template<class T>
    vector<T> operator+(vector<T> x, vector<T> y) {
        vector<T> result;
        result.reserve(x.size());
        for (size_t i = 0; i < x.size(); i++)
            result[i] = x[i] + y[i];
        return result;
   }
}

但我认为这是不好的做法,因为clang-tidy警告我“修改std命名空间会导致未定义的行为”。在为STL类重载运算符时还有其他更好的做法吗?

c++ vector std
5个回答
6
投票

最佳做法是不要这样做。

但是,如果你真的想要你仍然可以:只是不要把它放在命名空间std

并且不要通过值来接受你的论证,除非你故意这样做以便充分利用移动语义(你不是)。


4
投票

我建议:

  1. 不要使操作员超载。改为创建常规函数。
  2. 将函数放在特定于您的应用程序的namespace中。

例:

namespace MyApp
{
   template <typename T>
   std::vector add(std::vector<T> const& lhs, std::vector<T> const& rhs) { ... }

   template <typename T>
   std::vector& append(std::vector<T>& lhs, std::vector<T> const& rhs) { ... }
}

4
投票

将函数插入std会使您的程序生成错误,无需诊断。

在某些有限的情况下,你可以在std中插入专业,但是这不能做你想要的。

所以你不能将vec + vec插入std

将操作符放在不同的命名空间中是合法的,但不明智。当通过ADL / Koenig查找无法找到操作员时,操作员无法正常工作。看似合理的代码,如std::accumulate( vec_of_vec.begin(), vec_of_vec.end(), std::vector<int>{} )无法编译,以及其他问题。

简短的回答是,vector不是你的类型。不要这样做。

您可以在其他地方创建辅助函数,例如util::elementwise_add( vec, vec )

std没有实施+,因为连接和元素操作都是合理的。 valarray确实实现了元素操作;可能你想要的是std::valarray<int>而不是std::vector<int>

如果失败了,您可以在自己的命名空间中编写一个命名运算符vec +by_elem+ vec或从std::vector继承,使用该类型,并为您的类型重载+。 (从std::vector继承是非常安全的;只要没有人使用堆分配到std::vectors或类似的原始指针)


2
投票

无论你将operator+(...)添加为add(...)还是函数template<class T> std::vector<T> operator+(std::vector<T> x, const std::vector<T>& y) { assert(x.size() == y.size()); for (std::size_t i = 0; i < x.size(); ++i) x[i] += y[i]; return x; } ,你最好这样做:

this comment

通过按值获取第一个向量(而不是const-ref),您将强制编译器自动为您创建一个副本来保存结果。

阅读+后增加。

由于a + b + c从左到右的相关性,像(a + b) + c这样的表达式被解析为operator+(... x, ... y)。因此,如果a + b中的第一个(而不是第二个)参数是按值获取的,那么x返回的prvalue可以移动到#include <iostream> #include <vector> template<class T> class MyVec : public std::vector<T> { public: MyVec& operator+=(const T& add) { reserve(1); push_back(add); return *this; } }; int main() { MyVec<int> vec; vec += 5; vec += 10; for (auto& e : vec) { std::cout << e << "\t"; } std::cin.get(); } 。否则,将进行不必要的复制。


0
投票

您可以创建自己的vector类继承自std :: vector并定义new运算符

vec + 20 + 30;

编辑:sry我不知道这个解决方案会导致未定义的行为。然后我建议在上面的帖子中显示类似的解决方案。但为什么你需要plus运算符?不是push_back够好吗?您可以实现引用返回值以继续添加。所以你可以这样做:

qazxswpoi

添加两个元素(20和30)。这是更少的代码,但更具可读性?

© www.soinside.com 2019 - 2024. All rights reserved.