operator []如何在C ++中工作(在用户定义的对象上重载)?

时间:2014-10-28 00:30:37

标签: c++ arrays vector operator-overloading

据我所知,开发人员可以重载operator[]来获取或设置某些内容,具体取决于运营商所处的位置。例如,您可以obj[2] = test_obj;test_obj = obj[2]。但是我不明白第一个例子是如何工作的; operator[]返回对堆上某些内容的引用,因此当obj[2] = test_obj;运行时,会发生什么?如果索引2已存在某些内容,是否会被删除? 2中对象的析构函数首先被调用吗?如何完成这一切,因为operator[]的方法体中没有进行这种检查?

2 个答案:

答案 0 :(得分:3)

引用的工作方式与指针非常相似,但引用始终指向某些实际值。

enter image description here

因此,当operator[]返回引用并分配给该引用时,您将直接指定引用引用的值。在您的示例中,这将是位于索引2的对象。请注意,返回的Container::operator[]类型不是对Container的引用,而是通常是对包含值的引用。 / p>

要给出详细的答案,它取决于相关类型的operator[]的实际返回类型。如果返回类型是对基本类型的引用,那么它就像对基元的任何其他引用一样工作。没有涉及破坏者。赋值直接在引用的值中进行。例如:

int x = 5;
x = 6;

没有调用析构函数。没有操作员被调用。 x包含的值将替换为赋值运算符右侧的值。

同样,如果涉及参考:

int x = 5;
int &r = x;
r = 6;

没有调用析构函数。没有操作员被调用。 r点(在本例中为x)的值将替换为赋值运算符右侧的值。

同样,如果涉及非基本类型,则将调用给定类型的operator=

Foo x;
Foo y;
// Foo::operator=(const Foo &) is called on x with an argument referencing y
x = y;

必然会调用xy的析构函数。

与参考文献相同:

Foo x, y;
Foo &r = x;
// Foo::operator=(const Foo &) is called on x with an argument referencing y
r = y;

但是,operator[]不是必需来返回引用;虽然,强烈鼓励这一点。

对于非引用或对非基本类型的引用,将调用返回值的operator=,因此赋值运算符的行为也很重要。

operator=的情况下,不调用左侧的析构函数,但赋值运算符本身负责任何清理。这就是为什么赋值运算符通常是根据copy-swap idiom实现的。

因此,在std::vector<int>的情况下,std::vector<int>::operator[]会返回int &。赋值发生在参考点所在的位置。

对于std::vector<Foo>std::vector<Foo>::operator[]返回Foo &并调用Foo::operator=(const Foo &)

但是,正如我所提到的,类可以从operator[]返回任意对象,并且将调用该对象的赋值运算符。这可以用于通过另一个对象代理赋值。您可能会在Matrix类中找到一个返回Row对象的地方,该对象可能会实现operator[]。同样不一定推荐这种设计,但这并非闻所未闻。在这些情况下,返回类型可能根本不是引用,而是实际值。但是,它仍然可以以相同的方式工作Row::operator=Proxy::operator=负责分配和清除所需的任何资源。这就是Rule of Three如此重要的原因。

答案 1 :(得分:1)

由于operator[]通常会返回引用,因此它的工作原理与左侧的引用完全相同:

Foo& j;
j = test_obj;

引用基本上与常规变量在左侧相同,因为引用基本上只是引用变量的另一种方式。所以它基本上与:

相同
Foo j;
j = test_obj;

所以它基本上只是copy assignment,使用Foo::operator=(Foo const&)(它总是存在于C ++中)。 (即使它被删除,它仍然存在 - 如果你试图称它被删除,而不是没有函数存在,你会收到错误。)

相关问题