我已经开始学习C++,所以由于我缺乏知识/经验,我不知道为什么对于菜鸟来说看似简单的东西(就像我将要描述的那样)在STL中还没有。要将一个向量添加到另一个向量,您必须输入以下内容:
v1.insert(v1.end(), v2.begin(), v2.end());
我想知道在现实世界中人们是否只是重载 += 运算符以使其不那么冗长,例如达到
的效果template <typename T>
void operator+=(std::vector<T> &v1, const std::vector<T> &v2) {
v1.insert(v1.end(), v2.begin(), v2.end());
}
那么你就可以
v1 += v2;
我还设置了将push_back 设置为“+=”单个元素到末尾。精通 C++ 的人是否不应该做或特别避免这些事情?
这实际上是我希望以
append()
重载的形式看到此功能的情况。 operator+=
有点不明确,你的意思是把每个向量的元素互相相加吗?或者你想追加?
但是,就像我说的,我会欢迎:
v1.append(v2);
它很清晰简单,我不知道为什么它不存在。
我认为主要原因是
+=
的语义不明显。这是您在这里的含义,但还有一个同样有效的含义,即相等大小向量的每个元素的按元素相加。由于这种模糊性,我认为他们决定最好依靠用户直接调用 insert
。时才应重载运算符。* 这意味着,例如,如果两个对象的乘积没有数学定义,则不要重载这些对象的乘法运算符。如果存在数学对应关系,则运算符重载可以通过允许以 a*b + c 的形式表达方程而不是更冗长的 (a.multiply(b)).add(c) 形式来表达类,从而使类更方便使用使用加法和乘法运算符时,加法和乘法应该是本意。任何其他含义很可能会让其他人感到困惑。其他一些可以接受重载运算符的类型(在我看来,
更可取)是智能指针、迭代器、复数、向量和 bignum。 这遵循 C++ 的设计目标之一,即应该可以定义与内置类型一样易于使用的类。当然,您可以在类上定义一些也不是数学概念的运算符。您可能希望重载 == 和 != 运算符,而不是编写 isEqual 方法,并且可能希望重载 =,因为编译器的默认赋值运算符不是您想要的。
另一方面,重载运算符来执行意想不到的操作(例如定义 ^ 将字符串翻译为日语)是晦涩且危险的。你的程序员同事不会高兴地发现看起来像是排他或比较的东西实际上是非常不同的。那么解决方案是编写类,以便轻松编写
clear和maintainable代码,无论这意味着使用运算符重载还是避免它。 将两个向量相加过于模糊,无法定义运算符。正如其他人所表明的那样,许多人对其含义有不同的看法,而对于字符串来说,人们普遍认为将两个字符串添加在一起意味着串联。在您的示例中,尚不完全清楚您是否想要对所有元素进行组件明智的添加,在末尾添加一个元素,还是将两个向量连接在一起。尽管这样做可能更简洁,但使用运算符重载来创建您自己的编程语言并不是最好的方法。
*是的,我知道 Stroustrup 重载
> 来进行流操作而不是位移。但与算术和指针运算符相比,这些运算符一开始并不经常使用,并且可以说,现在每个人都知道如何使用 cout,人们普遍认为> 是插入器和提取器运算符。 (他最初尝试仅使用 << and > 进行输入和输出,但这些运算符的含义在每个人的脑海中根深蒂固,以至于代码无法阅读。)<< and > < and >
std::string
,它因其整体设计而受到 Herb Sutter 的严厉批评。
a
既可以是左值引用,也可以是右值引用。
template <class T, class U, typename std::enable_if<std::is_same<typename std::remove_cv<typename std::remove_reference<U>::type>::type, std::vector<T>>::value, bool>::type = true>
U append(U && a, const std::vector<T> & b) {
a.insert(a.end(), b.cbegin(), b.cend());
return std::forward<U>(a);
}