我有一个简单的结构来容纳两个const double

struct Scale {
    const double SCALE_X, SCALE_Y;

    Scale(double, double);
};

Scale::Scale(double sx, double sy) :
SCALE_X(sx), SCALE_Y(sy) {
}

我有此函数,该函数返回 bool(boolean) 值作为确认,并将传递的oscale指针设置为内部找到的任何计算值。
bool FindSequence(Scale* oscale) {
    // ...
    *oscale = Scale(sx, sy);
    // ...
    return true;
}

正在使用:
Scale *scale;
if (FindSequence(scale)) {
    std::cout << "Yes" << std::endl;
}

编译日志:
photon.cpp:286:14: error: use of deleted function 'photon::Scale& photon::Scale::operator=(photon::Scale&&)'
      *oscale = Scale(sx, sy);
              ^
In file included from photon.h:5:0,
                 from photon.cpp:4:
globals.h:76:9: note: 'photon::Scale& photon::Scale::operator=(photon::Scale&&)' is implicitly deleted because the default definition would be ill-formed:
  struct Scale {
         ^
globals.h:76:9: error: non-static const member 'const double photon::Scale::SCALE_X', can't use default assignment operator
globals.h:76:9: error: non-static const member 'const double photon::Scale::SCALE_Y', can't use default assignment operator

我是否必须重写operator =?是因为Scale结构是不可变的吗?我究竟做错了什么?

最佳答案

这里有几个问题。我将一一介绍。

const double SCALE_X, SCALE_Y;

这是您问题的主要根源。如果类具有const成员,则编译器将不会生成副本构造函数或副本赋值运算符;您必须自己生成它们。

但是,我认为这些成员甚至都不应该是const。如果某人具有Scale对象,则他们应该能够更改其值,但是如果他们具有const Scale对象,则他们将无法更改,因为所有(非mutable)数据成员在const上访问时都会“成为” const目的。

换句话说,让类的使用者决定他们是否要让实例为只读;非const Scale对象应该是可变的!

通过这一更改,编译器将能够生成合理的副本构造函数和合理的副本赋值运算符,从而消除特定的错误。

但是,您在这里确实还有另一个错误:
Scale *scale;
if (FindSequence(scale)) {

您正在传递未初始化的指针。一旦FindSequence()取消引用此指针,便会调用未定义的行为,并且您的程序可能会崩溃。

通常,您可以使用引用进行此操作:
bool FindSequence(Scale & oscale) {

然后,调用代码变为以下代码(只需删除*):
Scale scale;
if (FindSequence(scale)) {

但是要做到这一点,您将需要一个默认的构造函数。一个理智的选择是将其初始化为零成员:
Scale::Scale() : SCALE_X(0), SCALE_Y(0) { }

(或者,您可以只执行Scale scale(0, 0);。)

应用这三个更改,编译器应该克服这些问题。 (当然,它可能会遇到其他问题,但是这些更改将解决您的问题。)

关于c++ - C++中的指针分配,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27351915/

10-15 00:21
查看更多