(C ++)覆盖运算符<<打印错误的对象

时间:2018-12-09 19:25:12

标签: c++ operator-overloading

我现在正在对标量和向量进行运算符覆盖,并在运算符中苦苦挣扎<<< / p>

这是我的代码优先

main :(我不能更改main ...它将像这样给出,我只编码cpVector,cpScalar)

#include <iostream>
#include "cpScalar.hpp"
#include "cpVector.hpp"
#include <iostream>
#include <string>

using namespace std;

int main(){

cpScalar arr[4];
for(int i = 0; i < 4; i++){
    arr[i] = cpScalar(i+1);
}
cpVector v1(arr, 4);          // {1, 2, 3, 4}
cpScalar arr2[4];
for(int i = 0; i < 4; i++){
    arr2[i] = cpScalar(i+3);
}
cpVector v2(arr2, 4);         // {3, 4, 5, 6}

cpVector result4 = v2 / v1;   //  {0.3, 0.4, 0.5, 0.6}

cout << result4.getVal(0) << " " ... " "  << result4.getVal(3) << endl;
cout << result4 << endl;
// prints   0.3, 0.4, 0.5, 0.6   and     [, , , ]
}

当我检查结果4的每个值时,我可以找到操作员/工作对象。 但是,当我尝试打印整个矢量时,它会打印一个空值。 这是cpVector类。

cpVector:

#ifndef CPVECTOR_H
#define CPVECTOR_H
#include "cpScalar.hpp"
#include <iostream>
#include <string>
#include <cassert>

using namespace std;
class cpVector
{
    private:
        cpScalar *data;
        unsigned int size;

    public:
        cpVector() {
            cpScalar s[0];
            data = s;
            size = 0;
        }

        cpVector(cpScalar sarr[], unsigned int s){
            this->size = s;
            data = sarr;
        }

        cpVector operator/(cpVector s){
            assert(size == s.getSize());

            unsigned int x = s.getSize();
            cpScalar denom = s.getAbs();
            cpScalar ans[x];
            for (int i=0; i < x;i++){
                ans[i] = data[i] / denom;
                std::cout << i << "th element: " << ans[i] << std::endl;
            }
            return cpVector(ans, x);
        }

        friend std::ostream& operator<<(std::ostream& s, const cpVector &r);

        cpScalar getVal(int i)const{return data[i];}

        int getSize() const{return size;}

        cpScalar getAbs() const{
            cpScalar sum(0);
            for(int i = 0; i < size; i++){
                cpScalar x = data[i];
                if(x.getDouble() < 0 && x.getInt() < 0){
                    x = x * cpScalar(-1);
                }
                sum = sum + x;
            }
            return sum;
        }
};

std::ostream& operator<<(std::ostream& s, const cpVector &r) {
            s.put('[');
            if(r.getSize() > 0){
                s << r.getVal(0);
                for (int i = 1; i < r.getSize(); i++) {
                    s << ", " << r.getVal(i);
                }
            }
            return s << ']';
        };

#endif // CPVECTOR_H

cpScalar:

#ifndef CPSCALAR_H
#define CPSCALAR_H
#include <iostream>
#include <string>
#include <cassert>

const int invalid = 99999999;

class cpScalar
{
     private:
        int intData;
        double doubData;
        char dType;

    public:
        cpScalar() {
            intData = invalid;
            doubData = invalid;
            dType = ' ';
        }
        cpScalar(int d) {
            intData = d;
            doubData = invalid;
            dType = 'i';
        }
        cpScalar(double d) {
            intData = invalid;
            doubData = d;
            dType = 'd';
        }

        cpScalar operator+ (cpScalar &s){
            if (getType() == 'i' && s.getType() == 'i'){
                return cpScalar(getInt() + s.getInt());
            }else if (getType() == 'd' && s.getType() == 'i'){
                return cpScalar(getDouble() + s.getInt());
            }else if (getType() == 'i' && s.getType() == 'd'){
                return cpScalar(getInt() + s.getDouble());
            } else if (getType() == 'd' && s.getType() == 'd'){
                return cpScalar(getDouble() + s.getDouble());
            }
            return cpScalar(invalid);
        }

        cpScalar operator/ (cpScalar s){
            assert(s.getDouble() != 0 && s.getInt() != 0);

            if (getType() == 'i' && s.getType() == 'i'){
                if(getInt() % s.getInt() == 0) return cpScalar(getInt() / s.getInt());
                else return cpScalar(1.0 * getInt() / s.getInt());
            }else if (getType() == 'd' && s.getType() == 'i'){
                return cpScalar(getDouble() / s.getInt());
            }else if (getType() == 'i' && s.getType() == 'd'){
                return cpScalar(getInt() / s.getDouble());
            } else if (getType() == 'd' && s.getType() == 'd'){
                return cpScalar(getDouble() / s.getDouble());
            }
            return cpScalar(invalid);
        }

        cpScalar operator* (cpScalar s){
            if (getType() == 'i' && s.getType() == 'i'){
                return cpScalar(getInt() * s.getInt());
            }else if (getType() == 'd' && s.getType() == 'i'){
                return cpScalar(getDouble() * s.getInt());
            }else if (getType() == 'i' && s.getType() == 'd'){
                return cpScalar(getInt() * s.getDouble());
            } else if (getType() == 'd' && s.getType() == 'd'){
                return cpScalar(getDouble() * s.getDouble());
            }
            return cpScalar(invalid);
        }

        friend std::ostream& operator<< (std::ostream &sout, const cpScalar &d);

        int getInt() const{return intData;}

        double getDouble() const{return doubData;}

        char getType() const{return dType;}

};
        std::ostream& operator<<(std::ostream &sout, const cpScalar &d) {
            if(d.getType() == 'i') sout << d.getInt();
            else if (d.getType() == 'd') sout << d.getDouble();
            return sout;
        };
#endif // CPSCALAR_H

感谢阅读

1 个答案:

答案 0 :(得分:0)

您不能存储指向在堆栈上分配的临时变量的指针。当临时对象在其作用域的末端不再存在时,指针将不再有效。

例如,使用以下代码(请注意,为简便起见,在这些示例中,我省略了数组值的初始化):

struct Foo
{
  int* data;
  Foo( int* d )
  : data( d )
  {
  }
};

Foo makeFoo( size_t size )
{
  int bar[ size ]; // note this in invalid c++, only allowed by a gcc extension
  return Foo( bar );
}

int main()
{
  Foo f = makeFoo( 4 );
  std::cout << f.data[ 0 ]; // undefined behaviour, f.data points to and array that no longer exists
}

数组barmakeFoo结尾之后不存在,并且返回的Foo的{​​{1}}指针指向已释放的内存。请注意,如果您运行上述代码,则可能会打印正确的输出,因为即使数组不再存在,其值也不会被覆盖,因为在我们打印输出之前,没有其他函数会使用堆栈。

针对此问题的大多数C ++解决方案是使用data

std::vector

如果您的作业不允许您使用struct Foo { std::vector< int > data; Foo( const std::vector< int >& data ) : data( d ) // make a copy of the temporary vector, no more undefined behaviour { } }; Foo makeFoo( size_t size ) { std::vector< int > bar( size ); return Foo( bar ); } (我讨厌通过不允许您使用语言和标准库的关键功能来尝试教您C ++的作业),那么您将需要使用指针:

std::vector

您将需要确保实现在数组上调用struct Foo { int* data; Foo( int* d ) : data( d ) { } }; Foo makeFoo( size_t size ) { int* bar = new int[ size ]; return Foo( bar ); } 的析构函数,否则会发生内存泄漏并记下rule of three并实现或删除复制构造函数和赋值运算符

为避免此问题,我们应该使用delete[]来为我们删除数组并避免3/5问题的发生:

std::unique_ptr

请注意,因为不可能复制struct Foo { std::unique_ptr< int[] > data; Foo(std::unique_ptr< int[] >&& d) : data( std::move( d ) ) { } }; Foo makeFoo(size_t size) { std::unique_ptr< int[] > bar( new int[ size ] ); return Foo( std::move( bar ) ); } ,我们必须使用std::unique_ptr来移动值而不是复制它们。您还需要使用std::move来移动Foo对象,而不是复制它们。有关移动对象如何在C ++中工作的信息,请参见https://en.cppreference.com/w/cpp/language/move_constructor(对于初学者来说可能有些高级,但这是现代C ++的关键功能)。如果您无法移动物体,可以改用std::move:(只需在上面的示例中将std::shared_ptr替换为std::unique_ptr并删除std::shared_ptr),即可复制,但请注意,如果您复制std::move对象,则两个副本都将指向相同数据。