在本地范围内初始化时避免对象破坏,C++

Avoid object destruction when initializing in local scope, C++

我正在做一个网络项目,我需要在 try-catch 块中初始化一个对象。我希望表示套接字的对象在销毁时关闭套接字,但我必须避免在使用套接字之前关闭它。套接字用整数值这样简单的东西表示,这就是为什么关闭它很容易,或者说很难避免。

本质上,我有以下(简化的)代码:

#include <iostream>

using namespace std;

struct Foo {
    int v;

    Foo() {
        cerr << "Foo default constructor with v = " << v << ".\n";
    }

    Foo(int newV) : v(newV) {
        cerr << "Foo constructor with v = " << v << ".\n";
    }

    ~Foo() {
        cerr << "Foo destructor with v = " << v << ".\n";
    }
};

int main()
{
    Foo foo;
    try {
        foo = Foo(3);
    } catch (...) {
        // handle exception
    }
}

产生以下输出:

Foo default constructor with v = 0.
Foo constructor with v = 3.
Foo destructor with v = 3.
Foo destructor with v = 3.

这对我来说是个问题,因为 Foo 被销毁了两次,值为 3。一次,在程序结束时,一次在分配操作后退出 try 块之后。

我的问题是:我可以通过销毁其默认值并就地构造它来实例化一个对象,而不是构造另一个对象并执行赋值吗?

当然,有一些解决方法,比如使用 new,但我不想被迫在任何地方取消引用一个对象,而且我想确保它在出现错误时被销毁(尽管当然,我可以使用一些指针包装器)。我也不想使用一些单独的 C 风格的初始化方法,因为我认为那很丑陋。我的“Foo”class 中还有其他成员,所以我需要在分配期间执行某种破坏,这很不方便。理想情况下,我希望看到类似于

的内容
Foo foo;
try {
    Foo foo(3);
} catch (...) {
    // handle exception
}

但我不能那样做,因为这会导致重新声明,或者更确切地说是影子声明,最重要的是,更本地化的 Foo 对象无论如何都会被销毁。

我刚打完题就想到了这个。使用 move-assignment.

取原来的代码,在class定义中加入如下方法:

Foo & operator=(Foo && other) {
    swap(v, other.v);
    return *this;
}

这样,当构造一个对象只是为了将其分配给其他某个对象时,将调用此方法,它会简单地交换 v 成员中的值。 other 对象将立即被销毁,但具有 v.

的“旧”值

注意默认给v赋一些无意义的值,可能是-1.

现在,程序的输出是

Foo default constructor with v = 0.
Foo constructor with v = 3.
Foo destructor with v = 0.
Foo destructor with v = 3.

这正是我要找的。