Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Can';t解释编译器&x27;行为_C++_Destructor_Operator Keyword - Fatal编程技术网

C++ Can';t解释编译器&x27;行为

C++ Can';t解释编译器&x27;行为,c++,destructor,operator-keyword,C++,Destructor,Operator Keyword,考虑以下简单代码: class A { public: int value; A(int value) { this->value = value; } ~A() { printf("destroying %d\n", value); } A operator ++() { return A(value + 1); } }; int main() { A a(1); printf("before increment: %d\n", a.va

考虑以下简单代码:

class A {
public:
    int value;
    A(int value) { this->value = value; }
    ~A() { printf("destroying %d\n", value); }
    A operator ++() { return A(value + 1); }
};

int main() {
    A a(1);
    printf("before increment: %d\n", a.value);
    a = ++a;
    printf("after increment: %d\n", a.value);
    return 0;
}
这将产生:

增量前:1
销毁2
增量后:2
销毁2

为什么
a
1的值在被销毁之前会增加

很简单:

a = ++a;

首先,创建一个新的临时
对象,该对象保存
2
value+1=2
),该对象被移动/复制到
a
,然后销毁(这是您看到的第一个
销毁2
打印)。现在,编译器生成的move/copy构造函数只执行成员的memcopy,在本例中为
value
<代码>值
分配给临时对象时为
2
,因此
a
值也将为
2
。因此,最后两个
printf
打印出来的
2
并不奇怪。

在operator++方法中,您创建了一个临时对象,当您从函数返回该对象时,该对象将被销毁。也应该有另一个副本的建设和销毁,但省略了这一个

当您将日志添加到构造函数中时,您也会更好地看到正在发生的事情。我还允许自己将printf改为cout,以获得更多c++风格的编码

#include <iostream>

class A {
public:
    int value;
    A(int value) {
        std::cout << "creating " << value << std::endl; 
        this->value = value; 
    }
    ~A() { 
        std::cout << "destroying " << value << std::endl; 
    }
    A operator ++() { return A(value + 1); }
};

int main() {
    A a(1);
    std::cout << "before increment: " << a.value << std::endl; 
    a = ++a;
    std::cout << "after increment: " << a.value << std::endl; 

    return 0;
}
您还可以阅读运算符重载的规范实现:

运算符++重载应如下所示:

struct X
{
    X& operator++() // prefix version
    {
        // actual increment takes place here
        return *this;
    }
    X operator++(int) // postfix version
    {
        X tmp(*this); // copy
        operator++(); // pre-increment
        return tmp;   // return old value
    }
};
基本上,为了清楚起见,您可以在这里将预增量运算符声明为常量

A operator ++() const { return A(value + 1); }
但预期的行为是:

A& operator ++() { ++value; return *this; }

你是指第一次还是第二次销毁?你的
操作符+++()
应该在自身递增后返回一个引用(对自身),而不是创建一个新的临时
a
。正如所写的,这段代码会让这个类的所有用户感到困惑。幸好您提到了实现这些运算符的合理方法。顺便说一句,如果OP以这种方式实现它,答案将是(如果内存服务器正确的话)未定义的行为,因为使用
a=++a在一个表达式中修改相同的对象++a
以将自身递增的方式实现,则表达式将导致未定义的行为。看见
A operator ++() const { return A(value + 1); }
A& operator ++() { ++value; return *this; }