我有一个结构,Foo,指针数组为Bar。
struct Foo
{
Bar* _BarList;
Foo()
{
_BarList = new Bar[1];
_BarList[0] = Bar(10, 20);
}
Foo& operator=(const Foo& foo)
{
Bar* tmpBarList = new Bar[1];
tmpBarList[0] = foo._BarList[0];
delete[] _BarList;
_BarList = tmpBarList;
return *this;
}
~Foo()
{
delete[] _BarList;
}
};
我称之为
Foo baz = fooFunc();
(似乎)如果我在函数(fooFunc)中创建一个Foo(f)实例并返回它,则在返回值之前调用析构函数,因为我丢失了_BarList的内容。
这在函数中创建是有意义的。这是一个例子。
Foo fooFunc()
{
Foo f = Foo();
return f;
}
如果我在返回时直接返回Foo的实例,则在调用equals运算符之后才会调用该项的析构函数(通过调用行上的equals语句)。
Foo fooFunc()
{
return Foo();
}
我认为这是有道理的,因为我在对象中创建了Foo,并且在返回对象之前清除了一些东西。
我想我可以通过这样做返回来解决这个问题(在编写一个新的构造函数来获取Foo之后):
Foo fooFunc()
{
Foo f = Foo();
return Foo(f);
}
1)我的假设是对的吗?
2)还有另一种方法可以不需要这么多的重复赋值运算符吗?
编辑:请注意,此功能通常不仅仅会返回Foo()!
答案 0 :(得分:5)
您的课程违反了Rule of three。您有一个析构函数和一个复制赋值运算符,但没有复制构造函数。默认情况下,不可以做你需要的。
并注意所有这些行:
Foo f = Foo();
return Foo(f);
Foo baz = fooFunc();
使用复制构造函数,而不是赋值运算符。赋值运算符仅用于分配现有对象,永远不会在创建/初始化新对象时使用。
答案 1 :(得分:3)
我认为您遇到的不同行为是由编译器优化造成的。
无论如何,
Foo baz = fooFunc();
需要一个拷贝构造函数来工作,因为它将从fooFunc返回一个构造一个新对象。
例如
Foo(const Foo& foo) : _BarList( NULL )
{
::operator=( foo );
}
这将保证将fooFunc()返回对象复制到本地声明的Foo baz对象。
注意:实际上,从复制构造函数调用operator=
是一种不好的做法(但我在这里提到它可以给你一个快速的答案,它会适用于你的情况)。查看此帖子:Copy constructor and = operator overload in C++: is a common function possible?