C++ 读取和写入的重载运算符[]

C++ 读取和写入的重载运算符[],c++,operator-overloading,C++,Operator Overloading,我在重载对象中的读写运算符[]时遇到问题。这是一个包含不同组件的大型代码,我不会把所有细节都放在这里,因为它不会有帮助。简而言之,我有以下几点 class MyObject(){ inline SetterProxy& operator[](int i) { SetterProxy a(i); return a; } inline double operator[](int i) const{

我在重载对象中的读写运算符[]时遇到问题。这是一个包含不同组件的大型代码,我不会把所有细节都放在这里,因为它不会有帮助。简而言之,我有以下几点

class MyObject(){
    inline SetterProxy& operator[](int i) {
        SetterProxy a(i);
        return a;
    }
    inline double operator[](int i) const{            
        return some_value;
    }
}
第一个重载[]可以很好地分配值如果您想知道SetterProxy是什么,我必须使用代理类,以便能够在分配值之前执行一些检查和内部函数调用。然而,第二个应该在读取时调用的函数不起作用,代码崩溃。我不确定这里发生了什么,但当我评论第一个时,它就工作得很好!编译器会不会因为两者都是内联的而混淆了它们

任何想法都将不胜感激

编辑: 好的,这是SetterProxy本身:

class SetterProxy{
private:
    Vec v;
    int i;
    double *ptr_val;
public:
    inline SetterProxy(Vec v_, int i_) {
        v = v_;
        i = i_;
        VecGetArray(v,&ptr_val);
    }
    inline ~SetterProxy(){
        VecRestoreArray(v,&ptr_val);
    }

    inline void operator=(double rhs ){
        ptr_val[i] = rhs;
    }
};

虽然我不认为这是直接的原因。最初我还让它按值返回,我认为将其更改为引用会更有效。我认为这应该是安全的,因为赋值是在Proxy operator=class中完成的,之后Proxy类将超出范围。不管怎样,这都不能解决我的问题

您正在返回对局部变量的引用-当运算符返回时,它超出范围,使您的引用悬空。如果您将警告设置设置到合理的水平,一个好的编译器应该警告您这一点。

正如@Stuart Golodetz的回答中所指出的,您正在返回一个对SetterProxy的引用,该引用引用是方法的本地引用,因此在返回时超出范围

相反,您应该按值返回SetterProxy实例:这应该没什么大不了的,SetterProxy可能只保留索引和对父对象的引用,因此编译器为其生成的复制构造函数就可以了,而且复制成本也不会太高


顺便说一句,除非您希望允许使用负索引,否则通常的习惯用法是对数组中的索引使用size\u t。

这可能与您在SetterProxy中执行的操作有关吗?你能用问题的摘要来更新这个问题吗?当它崩溃时,你是在常量对象上调用操作符[]还是在非常量对象上调用操作符[]?@seth:同时尝试了常量和非常量。调用printf%f\n,a[0];,之类的内容时,代码崩溃;。同样使用cout,我得到了一个编译错误,即操作符@SethCarnegie:unsigned int不能保证足够大以容纳任何可以分配的对象的大小,因此不能在其中包含索引;想想Windows x86_64:unsigned int是32位的,而size_t是64位的,因此unsigned int不能用作>4GB数组的索引,而size_t可以。请查看其他示例。@SethCarnegie:使用ptrdiff\u t,因为它的签名避免了麻烦,并且足够大。如果您正在为某些老式DSP编程,或者如果您愿意接受各种错误和一般性问题,以便看起来符合一般公众意见,和/或为了看起来符合标准库的惯例(支持现在已不存在的过时系统),请使用size\t。不用说,看似符合的理由在技术上是不可靠的。但有时牺牲技术上的东西会更好,特别是对于一个原始的管理者。@SethCarnegie:既然你在问,你可能认为你已经知道了答案,如果是真的,这意味着这个问题并不完全诚实,而且是为了欺骗。:-但无论如何,范围问题是16位系统的一个问题。C标准要求ptrdiff至少为17位。现在我打赌你不知道。一知半解是危险的,正如他们所说。@AlfP.Steinbach不,这是一个真实的问题,我不是想欺骗你,很抱歉你这么想。所以根据你的回答,我想我的问题的答案是肯定的,对吗?从你的回复中我真的看不出来,因为它似乎在谈论16位系统。@Seth:对不起。我误解了一个巧合。问题:例如,在读取printf语句中的值时,代码不应该调用第二个运算符吗?@GradGuy:不,调用哪个重载是由对象的常量决定的,而不是由您试图对返回值执行的操作决定的。如果你的对象不是常量,那么第一个重载总是被调用的。好吧。是否有必要要求编译器为只读目的调用第二个函数?@GradGuy:给它一个唯一的名称,或者在调用期间使对象为常量。但无论如何,我看不出有什么意义,因为如果第一个重载编写正确,即使是出于只读目的调用它也没有坏处。@ildjarn:问题是第一个重载使用代理设置值,因此它返回的是代理类的类型,因此printf对此抱怨!我想我必须写一个新的printf或重载