我现在正在对标量和向量进行运算符覆盖,并在运算符中苦苦挣扎<<< / 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
感谢阅读
答案 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
}
数组bar
在makeFoo
结尾之后不存在,并且返回的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
对象,则两个副本都将指向相同数据。