这不是我第一次提出关于折线问题的问题。这次我想在我的代码中讨论“C++ 中的复制和交换成语”。如果您有兴趣,可以在此处阅读问题说明。
因此,在我的代码中,我实现了 Copy-and-Swap 习惯用法:
void swap(Loman& a) {
std::swap(size, a.size);
std::swap(data, a.data);
}
Loman& operator=(const Loman& a)
{
Loman tmp(a);
swap(tmp);
return *this;
}
但在我看来,这段代码中有一个逻辑错字,实际上应该这样写:
void swap(Loman& first, Loman& second) {
std::swap(first.size, second.size);
std::swap(first.data, second.data);
}
Loman& operator=(const Loman& a)
{
Loman tmp(a);
swap(*this, tmp);
return *this;
}
在我看来, + 运算符中还有一个不必要的操作this-> size = size
。如果我删除它,什么都不会改变。
这是整个代码:
#include <iostream>
using namespace std;
class Loman
{
private:
int i=0;
int size;
int* data;
public:
Loman(int asize) {
size = 2*asize;
data = new int[size];
}
~Loman(){
delete[] data;
cout<<"Object destroyed\n";
}
Loman(const Loman &ob)
{
size = ob.size;
data = new int [size];
for(int i=0; i<ob.size; i++)
data[i] = ob.data[i];
}
void print(){
for(i=0; i<size; i++){
cout<<*(data+i)<<" ";
}
cout<<endl;
}
void scan(){
cout<<"Input "<<size/2<<" coordinates\n";
for(int i=0; i<size; i++){
cin>>*(data+i);
}
}
Loman operator+(Loman& ob){
this->size = size;
Loman tmp((size + ob.size)/2);
for(i=0; i<size; i++)
{
tmp.data[i]=*(data + i);//this->data[i]=data[i];
}
for(i=size; i<size + ob.size; i++) tmp.data[i] = ob.data[i-size];
return tmp;
}
void swap(Loman& a) {
std::swap(size, a.size);
std::swap(data, a.data);
}
Loman& operator=(const Loman& a)
{
Loman tmp(a);
swap(tmp);
return *this;
}
};
int main(){
Loman first(3);
Loman second(2);
first.scan();
second.scan();
Loman third(5);
third=first+second;
third.print();
return 0;
}
问题:我关于“+”运算符和交换函数的假设是否正确,如果不是,为什么不呢?
我错过了任何其他错误吗?
是否需要在swap函数中写using std::swap;
我从头开始。
这里不需要。
using std::swap;
,然后swap(x, y);
(已经没有)是对任意类型std::
的规范调用。swap
默认情况下,它会调用
std::swap
,但如果有此类型的函数swap
(ADL在其中找到它- 例如,在同一个命名空间中),那么它将被调用。但是由于这里你只在内置类型上调用它(而不是在类上),所以仍然没有 ADL,而且没有必要打扰。
从这里遵循关于您的功能的答案
swap
。如果您希望以这种方式调用它,那么它一定不能是非静态成员。(因为我们这样做swap(x, y);
,而不是x.swap(y);
。)你写的: - 这是完全错误的,因为这样的函数需要三个对象,而不是两个(结果
void swap(Loman &first, Loman &second)
是第三个是)。this
x.swap(y, z)
正确:
friend void swap(Loman& first, Loman& second) {...}
。有人会认为这样static
做可以,但不,ADL 不尊重他。添加一个移动构造函数也是值得的(
noexcept
不要忘记)。之后,最operator=
好像这样重写它:那么它将适合同时复制和移动。在任何情况下我都会使用这种形式(即使没有复制或移动构造函数)以免思考。
Loman operator+(Loman& ob)
必须替换为Loman operator+(const Loman &) const
以+
接受 const 和/或临时对象。同样,
void print() const
.B
operator+
什么都不做this->size = size;
。是同一个变量。混淆了到处写字的习惯
*(data+i)
。你不喜欢data[i]
什么?另一个令人困惑的想法是将 X 和 Y 混合存储在一个数组中。最好自己制作
struct Point {int x, y;}
并将其存储在数组中。然后,您无需费心将大小乘以 2。