【问题标题】:vector<Class> --- Question about Copy Constructor in Classvector<Class> --- 关于类中复制构造函数的问题
【发布时间】:2020-07-29 17:45:08
【问题描述】:

Upd:很抱歉,如果我用这样的问题打扰别人。我今年 48 岁。我正在努力寻找新的职业。我只需要“做这个”之外的更多信息。不要那样做。永远不要问为什么。 :) 感谢大家对我善良的人的回答和耐心:)

我有Class Car。

class Car {
protected:
    std::string Name;
    short Year;
    float Engine;
    float Price;
public:
Car() {
    Name = "ordinary";
    Year = 1980;
    Engine = 2.0;
    Price = 1000.;
}
Car(std::string name, short year, float engine, float price) {
    Name = name;
    Year = year;
    Engine = engine;
    Price = price;
}
Car(Car& other) {
    this->Name = other.Name;
    this->Year = other.Year;
    this->Engine = other.Engine;
    this->Price = other.Price;
}
Car(Car&& other) {
    this->Name = other.Name;
    this->Year = other.Year;
    this->Engine = other.Engine;
    this->Price = other.Price;
}
void operator= (Car& other) {
    this->Name = other.Name;
    this->Year = other.Year;
    this->Engine = other.Engine;
    this->Price = other.Price;
}

inline std::string GetName() const { return Name; }
inline short GetYear() const { return Year; }
inline float GetEngine() const { return Engine; }
inline float GetPrice() const { return Price; }
inline void SetName(std::string n) { Name = n; }
inline void SetYear(short y) { Year = y; }
inline void SetEngine(float e) { Engine = e; }
inline void SetPrice(float p) { Price = p; }
void InitCar(std::string name, short year, float engine, float price) {
    Name = name;
    Year = year;
    Engine = engine;
    Price = price;
}
void ShowCar() {
    std::cout << "Car_Name: " << Name << ";\nYear: " << Year
        << "; Engine: " << Engine << "; Price: " << Price << "\n";
    }
};

然后我创建 Car 对象的向量。

std::vector<Car> base;

现在

base.push_back(Car());

这对于编译器来说是可以的。 接下来也可以:

base.push_back(Car("this_car", 1900, 1.5, 1000));

但是下一个不行:

Car car("that_car", 2001, 3.0, 3000);
base.push_back(car);

编译器说:

没有可用的复制构造函数

当我从 Class Car 中获取 Copy Constructor 时,一切正常。

谁能解释为什么我应该从 Car 类中删除 Copy Constructor?

感谢大家的帮助和耐心。

【问题讨论】:

  • 您为什么要编写自己的用户定义的复制、赋值和移动函数?没有理由这样做。
  • 好吧,没有我自己的用户定义的复制、分配和移动功能——一切都很好。但我的问题是“为什么我做不到?”
  • 当然效果很好,因为这些函数的编译器版本就是这样设计的。您所做的只是让错误更容易发生。
  • 编译器是对的,没有copy-constructor。作为提示,您的移动构造函数不会移动任何东西,它只是复制所有内容。
  • 这是在不必要时编写自己的运算符的另一个缺点——您失去了编译器能够优化移动和复制的所有优势。一旦您介入并编写自己的代码,您将负责所有这些工作。

标签: c++ copy-constructor


【解决方案1】:

复制构造函数的正确声明应该是:

Car(const Car& other)

与复制赋值运算符相同,它也需要返回值Car&amp;

Car& operator= (const Car& other)
{
    ...
    return *this;
}

此外,您的移动构造函数实现不正确。它复制 Name 成员,而不是移动它。它应该看起来像这样:

Car(Car&& other) {
    this->Name = std::move(other.Name);
    this->Year = other.Year; other.Year = 0;
    this->Engine = other.Engine; other.Engine = 0;
    this->Price = other.Price; other.Price = 0;
}

而且你需要添加一个移动赋值运算符:

Car& operator= (Car&& other) {
    this->Name = std::move(other.Name);
    this->Year = other.Year; other.Year = 0;
    this->Engine = other.Engine; other.Engine = 0;
    this->Price = other.Price; other.Price = 0;
    return *this;
}

在这种情况下,可以实现复制赋值和移动赋值运算符,分别使用复制构造函数和移动构造函数(参见What is the copy-and-swap idiom?):

Car& operator= (const Car& other) {
    Car temp(other);
    std::swap(this->Name, temp.Name);
    this->Year = temp.Year;
    this->Engine = temp.Engine;
    this->Price = temp.Price;
    return *this;
}

Car& operator= (Car&& other) {
    Car temp(std::move(other));
    std::swap(this->Name, temp.Name);
    this->Year = temp.Year;
    this->Engine = temp.Engine;
    this->Price = temp.Price;
    return *this;
}

在这种情况下,您可以通过按值而不是按引用传递参数,将复制赋值和移动赋值运算符组合成一个实现,从而允许调用者决定是使用复制还是移动语义:

Car& operator= (Car other) {
    std::swap(this->Name, other.Name);
    this->Year = other.Year;
    this->Engine = other.Engine;
    this->Price = other.Price;
    return *this;
}

话虽如此,由于std::string 已经实现了正确的复制和移动语义,您应该让编译器为您生成复制/移动构造函数和复制/移动赋值运算符的默认实现:

class Car {
protected:
    std::string Name;
    short Year;
    float Engine;
    float Price;
public:
    Car() : Car("ordinary", 1980, 2.0, 1000)
    {
    }

    Car(std::string name, short year, float engine, float price)
        : Name(name), Year(year), Engine(engine), Price(price)
    {
    }

    Car(const Car&) = default;
    Car(Car&& other) = default;

    Car& operator= (const Car&) = default;
    Car& operator= (Car&&) = default;

    ...
};

【讨论】:

    【解决方案2】:

    您应该为复制构造函数参数指定 const

    Car(const Car& other) {
        this->Name = other.Name;
        this->Year = other.Year;
        this->Engine = other.Engine;
        this->Price = other.Price;
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 2014-06-13
    • 2012-11-03
    • 2011-05-29
    相关资源
    最近更新 更多