【问题标题】:Use of array subscription operator数组订阅运算符的使用
【发布时间】:2012-11-30 13:34:52
【问题描述】:

我定义了一个类 complex 和类 signal。 我已经为复杂的类重载了 + 和 - 。 信号类是用复杂类型complex *sig_Data; 的成员定义的,我使用数组订阅信号如下

complex &operator[](int i)
    {
        if(i >= range_start && i <= range_end) return sig_Data[zero_pt+i];
        else return complex(0);
    }

zero_pt 用作参考。

对于信号类的 + 运算符重载,我使用了这个

signal operator+(signal &a, signal &b)
{
    int r_start = min(a.range_start, b.range_start);
    int r_end = max(a.range_end, b.range_end);
    int z_pt = max(a.zero_pt, b.zero_pt);
    signal temp(r_start, r_end, z_pt);
    for(int i = r_start; i <= r_end; i++)
    {
        temp[i] = a[i] + b[i];
    }
    return temp;
}

当我在调试中使用 VC++ 检查值时,添加似乎在这里正确发生,但它们没有被分配给 temp。 我什至尝试使用带有复制交换习语 (What is the copy-swap idiom) 的赋值重载。

signal operator[](int i)函数中使用的构造函数是。

signal(int r_start, int r_end, int z_pt)
    {
        range_start = r_start;
        range_end = r_end;
        zero_pt = z_pt;
        int arr_ind = r_end - r_start;

        sig_Data = new complex [arr_ind];
    }

请帮我找出哪里出错了。

更完整的代码:

   #include <iostream>
    #include <conio.h>
    #include <string>

    #include <cstdlib>
    #include <cctype>
    #include <cstring>


    using namespace std;


    namespace Complex
    {
        class complex
        {
            double real;
            double imag;

        public:
            complex(double re = 0, double im = 0)
            {
                real = re;
                imag = im;
            }

            complex(complex &t)
            {
                real = t.real;
                imag = t.imag;
            }

            void StrtoComplex(const char *temp)
            {
                int i;

                for(i = 0; i < strlen(temp); i++)
                {
                    if(temp[i] == 'j' || temp[i] == 'i')
                        break;
                }

                real = atof(temp);//takes till the last valid char so after + or whitespace it ignores
                if(*(temp + i - 1) == '-')
                    imag = -atof(temp + i + 1);
                else
                    imag = atof(temp + i + 1);

            }

            friend complex operator+(complex &a, complex &b);
                    friend ostream &operator<<(ostream &s, complex &t);
            friend istream &operator>>(istream &s, complex &t);
            };
        //overloading + to add complex numbers
        complex operator +(complex &a, complex &b)
        {
            complex t;
            t.real = a.real + b.real;
            t.imag = a.imag + b.imag;
            return(t);
        }

        ostream &operator<<(ostream &s, complex &t)
        {
            s<<t.real<<" +j"<<t.imag;
            return s;
        }

        istream &operator>>(istream &s, complex &t)
        {
            std::string temp;

            std::getline(s, temp);
            t.StrtoComplex(temp.c_str());
            return s;
        }
    }

    namespace Discrete
    {
        using Complex::complex;
        class signal
        {
            complex *sig_Data;

            int range_start, range_end, zero_pt;

        public:
            signal()
            {
                sig_Data = NULL;
                range_start = range_end = zero_pt = 0;
            }

            signal(complex i)
            {
                sig_Data = new complex(i);
                range_start = range_end = zero_pt = 0;
            }

            signal(int r_start, int r_end, int z_pt)
            {
                range_start = r_start;
                range_end = r_end;
                zero_pt = z_pt;
                int arr_ind = r_end - r_start;

                sig_Data = new complex [arr_ind];
            }

            void StrtoSig(char *temp)
            {
                int arr_ind = 0;
                char *tok;

                if(!*temp) return;

                tok = temp;
                zero_pt = 0;
                //
                int flag;

                for(int i = 0; i < (flag = strlen(temp)); i++)
                {
                    tok++;
                    if(*tok == '^') zero_pt = arr_ind;
                    if(*tok == ',') arr_ind++;
                }
                range_start = 0 - zero_pt;
                range_end = arr_ind - zero_pt;

                sig_Data = new complex [arr_ind];
                tok = temp+1;
                for(int i = 0; i <= arr_ind; i++)
                {
                    if(*tok == ',') tok++;
                    while(isspace(*tok)) tok++;
                    if(*tok == '^') tok++;
                    sig_Data[i].StrtoComplex(tok);
                    while(*tok != ',' && *tok != '}'&& *tok != '\0') tok++;
                }
            }

            complex &operator[](int i)
            {
                if(i >= range_start && i <= range_end) return sig_Data[zero_pt+i];
                //else return complex(0);
            }


            friend signal operator+(signal &a, signal &b);
                    friend ostream &operator<<(ostream &s, signal &t);
    friend istream &operator>>(istream &s, signal &t);
        };

        //Overloading + operator
        signal operator+(signal &a, signal &b)
        {
            int r_start = min(a.range_start, b.range_start);
            int r_end = max(a.range_end, b.range_end);
            int z_pt = max(a.zero_pt, b.zero_pt);
            signal temp(r_start, r_end, z_pt);
            for(int i = r_start; i <= r_end; i++)
            {
                temp[i] = a[i] + b[i];
            }
            return temp;
        }


            ostream &operator<<(ostream &s, signal &t)
{
    s<<"{";
    for(int i = t.range_start; i <= t.range_end; i++)
    {
        if(i == (t.range_start + t.zero_pt))
            s<<" ^"<<t[i];
        else if(i == t.range_end)
            s<<" "<<t[i];
        else
            s<<" "<<t[i]<<",";
    }
    s<<"}";
    return s;
}

        istream &operator>>(istream &s, signal &t)
        {
            char *ip;
            s>>ip;
            t.StrtoSig(ip);
            return s;
        }
    }

   void main()
{
    using Discrete::signal;
    signal a,b,c;
    a.StrtoSig("{1+i5, ^7+i6}");
    b.StrtoSig("{5+i4, 7+i5}");

    c = a+b;
    cout<<c;
}

【问题讨论】:

  • 在您的订阅函数中,当索引超出范围时,您会返回 complex(0)。那么你将如何区分零元素和不正确的索引?
  • 返回对临时对象temp的引用是自找麻烦。 operator+ 应该返回一个副本。
  • @AshRj 这并不重要,因为我假设超出此界限的信号值为零......
  • 如果i 超出范围,您的signal::operator[] 将通过引用返回本地。不要那样做。 complex::operator+ 也是如此。
  • @aleguana 我会考虑你的建议,但即使返回 b4 也没有分配 temp

标签: c++ variable-assignment operator-keyword


【解决方案1】:

如果你希望能够通过operator[]修改类,它必须返回一个引用:

complex &operator[](int i)
{
    if(i >= range_start && i <= range_end) return sig_Data[zero_pt+i];
    else throw std::range_error("invalid index to operator[]");
}

当您返回一个值时,它会被复制到一个临时值中,因此分配给operator[] 的结果会在表达式末尾被丢弃。

【讨论】:

  • ...我这样做了,但没有帮助。除了有人建议我在这里不要使用参考..
  • @PSK 大约是operator+,它应该按值返回,而不是按引用返回。 operator[] 应该通过引用返回。
  • @PSK :我们没有说不通过引用返回......我们说不通过引用返回 locals。有区别;)
【解决方案2】:

好的,让我在心里为你调试代码

假设你有两个信号

signal s1 (5, 20, 8);
signal s2 (3, 25, 9);

现在您正在尝试添加然后

signal s = s1 + s2;

会发生什么:

  1. 你构造了一个temp 信号:

    信号温度 (3, 25, 9);

  2. 创建内部数组

    sig_Data = 新复合体 [22];

  3. 你的循环看起来像这样

    对于 (i = 3; i

  4. 对于每个i 你的operator[] 都会这样做

    if(i >= range_start && i

  5. 现在想象一个步骤,i = 15,它会这样做

    返回 sig_Data[9+15];

这违反了未定义行为的数组边界。

现在,我会留给你解决这个烂摊子。

PS Besies,你有内存泄漏,你从来没有delete[] sig_Data。即使你这样做了,你也会有一个堆损坏,因为你在你的复制构造函数中做了一个浅拷贝

【讨论】:

  • 我想这是我的错,但是您对我的代码的理解是错误的...我的range_start 永远不会大于零,而我的zero_pt 只是计数使范围相对于零......我也会添加一点代码
  • @PSK,举例说明您尝试添加的两个信号会重现问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-20
相关资源
最近更新 更多