在本地范围内初始化时避免对象破坏,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.
这正是我要找的。
我正在做一个网络项目,我需要在 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.
这正是我要找的。