C++ 相同的对象,每次都有不同的结果
C++ same object, different results each time
以下是我的项目的可运行片段。它假设是一个计算器,但我已将其简化为尽可能简单,同时仍然显示错误并正常运行。
对于此代码 :(
的错误格式、样式和所有其他问题,我深表歉意。有些只是为了保存space这里,比如空行。
Main.cpp
#include <iostream>
#include <string>
#include "Expression.h"
#include "ArithmeticExpression.h"
using namespace std;
int main() {
Expression *expr = new ArithmeticExpression("1+2+3", true);
expr->print();
delete expr; // Very intresting, if you don't delete it won't have the problem
expr = new ArithmeticExpression("1+2+3", true);
expr->print();
delete expr; // bug goes away if you don't delete
expr = new ArithmeticExpression("1+2+3", true);
expr->print();
delete expr; // ...
}
Expression.h
#ifndef EXPRESSION_H
#define EXPRESSION_H
#include <string>
int findOpIndex(std::string);
int evalLen(std::string);
class Expression {
public:
Expression() { }
virtual ~Expression() { }
float result;
std::string resultStr;
virtual std::string evaluate() { }
virtual void print() { }
};
#endif
算术Expression.h
#ifndef ArithmeticExpression_H
#define ArithmeticExpression_H
#include <iostream>
#include <string>
#include "Expression.h"
class ArithmeticExpression : public Expression {
protected:
bool isTopExpr;
bool isValue;
Expression *arithExpr;
Expression *left;
Expression *right;
public:
ArithmeticExpression() { }
ArithmeticExpression(std::string, bool);
~ArithmeticExpression();
std::string evaluate();
void print();
float convert(std::string);
};
#endif
Addition.h
#ifndef Addition_H
#define Addition_H
#include <string>
#include "Expression.h"
#include "ArithmeticExpression.h"
class Addition : public ArithmeticExpression {
protected:
Expression *left;
Expression *right;
public:
Addition(std::string, std::string);
~Addition();
std::string evaluate();
void print();
};
#endif
Expression.cpp
#include <iostream>
#include <string>
#include "Expression.h"
int findOpIndex(std::string expr) {
char curChar;
int bflag = 0;
int firstOp = -1;
for (unsigned int c=expr.length(); c>0; c--) {
curChar = expr[c];
if (curChar == '(') {
bflag++;
} else if (curChar == ')') {
bflag--;
} else if (bflag == 0) {
if (firstOp != -1) {
if (curChar == '+' || curChar == '-') {
return c;
}
} else if (curChar == '*' || curChar == '/') {
firstOp = c;
} else if (curChar == '+' || curChar == '-') {
return c;
}
}
}
return firstOp;
}
int evalLen(std::string eval) {
int count = 0;
for (unsigned int c=0; c<eval.length(); c++) {
if (eval[c] != '.') count++;
else break;
}
return count+3;
}
算术Expression.cpp
#include <stdlib.h>
#include <iostream>
#include "Expression.h"
#include "ArithmeticExpression.h"
#include "Addition.h"
ArithmeticExpression::ArithmeticExpression(std::string expr, bool isTopExpr) {
this->isTopExpr = isTopExpr;
int opIndex = findOpIndex(expr);
resultStr = expr;
if (opIndex == -1 || (opIndex == -1 && expr[0] == '-' && expr[1] != '(')) {
isValue = true;
arithExpr = NULL;
} else {
std::string leftExpr = expr.substr(0, opIndex);
std::string rightExpr = expr.substr(opIndex+1, expr.length());
arithExpr = new Addition(leftExpr, rightExpr);
}
}
ArithmeticExpression::~ArithmeticExpression() {
delete arithExpr;
}
std::string ArithmeticExpression::evaluate() {
if (isValue) {
return resultStr;
} else {
return arithExpr->evaluate();
}
}
void ArithmeticExpression::print() {
if (isTopExpr && isValue) {
std::string eval = evaluate();
std::cout << eval << " = " << eval << std::endl;
} else if (isTopExpr) {
std::string eval = evaluate();
arithExpr->print();
std:: cout << " = " << eval.substr(0,evalLen(eval)) << std::endl;
} else {
if (isValue) {
std::string eval = evaluate();
if (eval[0] == '-') std::cout << "(" << eval << ")";
else std::cout << evaluate();
} else {
arithExpr->print();
}
}
}
float ArithmeticExpression::convert(std::string s) {
return atof(s.c_str());
}
Addition.cpp
#include <iostream>
#include <string>
#include "Addition.h"
#include "ArithmeticExpression.h"
Addition::Addition(std::string leftStr, std::string rightStr) {
left = new ArithmeticExpression(leftStr, false);
right = new ArithmeticExpression(rightStr, false);
}
Addition::~Addition() {
delete left;
delete right;
}
std::string Addition::evaluate() {
float l = convert(left->evaluate());
float r = convert(right->evaluate());
r = convert(right->evaluate());
r = convert(right->evaluate());
return std::to_string(l+r);
}
void Addition::print() {
std::cout << "(";
left->print();
std::cout << "+";
right->print();
std::cout << ")";
}
我 运行 IT
时的输出
((1+2)+3) = 6.00
(1+2+3) = 4.00 // This evaluates correctly to 6.00 if
(1+2+3) = 4.00 // I don't delete the expr pointer in Main.cpp
这些值应该都相同。怎么了?
我没有使用复制构造函数;我确实写了它,但我意识到他们从未被调用过。
Valgrind 确认,所有内存都已释放并且析构函数正确地完成了它们的工作。
==20337== HEAP SUMMARY:
==20337== in use at exit: 72,704 bytes in 1 blocks
==20337== total heap usage: 22 allocs, 21 frees, 74,480 bytes allocated
==20337==
==20337== LEAK SUMMARY:
==20337== definitely lost: 0 bytes in 0 blocks
==20337== indirectly lost: 0 bytes in 0 blocks
==20337== possibly lost: 0 bytes in 0 blocks
==20337== still reachable: 72,704 bytes in 1 blocks
==20337== suppressed: 0 bytes in 0 blocks
==20337== Rerun with --leak-check=full to see details of leaked memory
==20337==
==20337== For counts of detected and suppressed errors, rerun with: -v
==20337== Use --track-origins=yes to see where uninitialised values come from
==20337== ERROR SUMMARY: 18 errors from 11 contexts (suppressed: 0 from 0)
72,704 bytes in 1 blocks
是编译器或 valgrind 中的错误。这段代码没有问题,因为我已经 运行 "hello world" 但它仍然说同样的话。
您未能初始化 ArithmeticExpression::isValue
。
ArithmeticExpression::ArithmeticExpression(std::string expr, bool isTopExpr) {
this->isTopExpr = isTopExpr;
int opIndex = findOpIndex(expr);
resultStr = expr;
if (opIndex == -1 || (opIndex == -1 && expr[0] == '-' && expr[1] != '(')) {
isValue = true;
arithExpr = NULL;
} else {
isValue = false; // add this line
std::string leftExpr = expr.substr(0, opIndex);
std::string rightExpr = expr.substr(opIndex+1, expr.length());
arithExpr = new Addition(leftExpr, rightExpr);
}
}
此外,我认为访问 expr[expr.length()]
不好,您应该更改
for (unsigned int c=expr.length(); c>0; c--) {
在Expression.cpp
到
for (unsigned int c=expr.length()-1; c>0; c--) {
以下是我的项目的可运行片段。它假设是一个计算器,但我已将其简化为尽可能简单,同时仍然显示错误并正常运行。
对于此代码 :(
的错误格式、样式和所有其他问题,我深表歉意。有些只是为了保存space这里,比如空行。
Main.cpp
#include <iostream>
#include <string>
#include "Expression.h"
#include "ArithmeticExpression.h"
using namespace std;
int main() {
Expression *expr = new ArithmeticExpression("1+2+3", true);
expr->print();
delete expr; // Very intresting, if you don't delete it won't have the problem
expr = new ArithmeticExpression("1+2+3", true);
expr->print();
delete expr; // bug goes away if you don't delete
expr = new ArithmeticExpression("1+2+3", true);
expr->print();
delete expr; // ...
}
Expression.h
#ifndef EXPRESSION_H
#define EXPRESSION_H
#include <string>
int findOpIndex(std::string);
int evalLen(std::string);
class Expression {
public:
Expression() { }
virtual ~Expression() { }
float result;
std::string resultStr;
virtual std::string evaluate() { }
virtual void print() { }
};
#endif
算术Expression.h
#ifndef ArithmeticExpression_H
#define ArithmeticExpression_H
#include <iostream>
#include <string>
#include "Expression.h"
class ArithmeticExpression : public Expression {
protected:
bool isTopExpr;
bool isValue;
Expression *arithExpr;
Expression *left;
Expression *right;
public:
ArithmeticExpression() { }
ArithmeticExpression(std::string, bool);
~ArithmeticExpression();
std::string evaluate();
void print();
float convert(std::string);
};
#endif
Addition.h
#ifndef Addition_H
#define Addition_H
#include <string>
#include "Expression.h"
#include "ArithmeticExpression.h"
class Addition : public ArithmeticExpression {
protected:
Expression *left;
Expression *right;
public:
Addition(std::string, std::string);
~Addition();
std::string evaluate();
void print();
};
#endif
Expression.cpp
#include <iostream>
#include <string>
#include "Expression.h"
int findOpIndex(std::string expr) {
char curChar;
int bflag = 0;
int firstOp = -1;
for (unsigned int c=expr.length(); c>0; c--) {
curChar = expr[c];
if (curChar == '(') {
bflag++;
} else if (curChar == ')') {
bflag--;
} else if (bflag == 0) {
if (firstOp != -1) {
if (curChar == '+' || curChar == '-') {
return c;
}
} else if (curChar == '*' || curChar == '/') {
firstOp = c;
} else if (curChar == '+' || curChar == '-') {
return c;
}
}
}
return firstOp;
}
int evalLen(std::string eval) {
int count = 0;
for (unsigned int c=0; c<eval.length(); c++) {
if (eval[c] != '.') count++;
else break;
}
return count+3;
}
算术Expression.cpp
#include <stdlib.h>
#include <iostream>
#include "Expression.h"
#include "ArithmeticExpression.h"
#include "Addition.h"
ArithmeticExpression::ArithmeticExpression(std::string expr, bool isTopExpr) {
this->isTopExpr = isTopExpr;
int opIndex = findOpIndex(expr);
resultStr = expr;
if (opIndex == -1 || (opIndex == -1 && expr[0] == '-' && expr[1] != '(')) {
isValue = true;
arithExpr = NULL;
} else {
std::string leftExpr = expr.substr(0, opIndex);
std::string rightExpr = expr.substr(opIndex+1, expr.length());
arithExpr = new Addition(leftExpr, rightExpr);
}
}
ArithmeticExpression::~ArithmeticExpression() {
delete arithExpr;
}
std::string ArithmeticExpression::evaluate() {
if (isValue) {
return resultStr;
} else {
return arithExpr->evaluate();
}
}
void ArithmeticExpression::print() {
if (isTopExpr && isValue) {
std::string eval = evaluate();
std::cout << eval << " = " << eval << std::endl;
} else if (isTopExpr) {
std::string eval = evaluate();
arithExpr->print();
std:: cout << " = " << eval.substr(0,evalLen(eval)) << std::endl;
} else {
if (isValue) {
std::string eval = evaluate();
if (eval[0] == '-') std::cout << "(" << eval << ")";
else std::cout << evaluate();
} else {
arithExpr->print();
}
}
}
float ArithmeticExpression::convert(std::string s) {
return atof(s.c_str());
}
Addition.cpp
#include <iostream>
#include <string>
#include "Addition.h"
#include "ArithmeticExpression.h"
Addition::Addition(std::string leftStr, std::string rightStr) {
left = new ArithmeticExpression(leftStr, false);
right = new ArithmeticExpression(rightStr, false);
}
Addition::~Addition() {
delete left;
delete right;
}
std::string Addition::evaluate() {
float l = convert(left->evaluate());
float r = convert(right->evaluate());
r = convert(right->evaluate());
r = convert(right->evaluate());
return std::to_string(l+r);
}
void Addition::print() {
std::cout << "(";
left->print();
std::cout << "+";
right->print();
std::cout << ")";
}
我 运行 IT
时的输出((1+2)+3) = 6.00
(1+2+3) = 4.00 // This evaluates correctly to 6.00 if
(1+2+3) = 4.00 // I don't delete the expr pointer in Main.cpp
这些值应该都相同。怎么了? 我没有使用复制构造函数;我确实写了它,但我意识到他们从未被调用过。 Valgrind 确认,所有内存都已释放并且析构函数正确地完成了它们的工作。
==20337== HEAP SUMMARY:
==20337== in use at exit: 72,704 bytes in 1 blocks
==20337== total heap usage: 22 allocs, 21 frees, 74,480 bytes allocated
==20337==
==20337== LEAK SUMMARY:
==20337== definitely lost: 0 bytes in 0 blocks
==20337== indirectly lost: 0 bytes in 0 blocks
==20337== possibly lost: 0 bytes in 0 blocks
==20337== still reachable: 72,704 bytes in 1 blocks
==20337== suppressed: 0 bytes in 0 blocks
==20337== Rerun with --leak-check=full to see details of leaked memory
==20337==
==20337== For counts of detected and suppressed errors, rerun with: -v
==20337== Use --track-origins=yes to see where uninitialised values come from
==20337== ERROR SUMMARY: 18 errors from 11 contexts (suppressed: 0 from 0)
72,704 bytes in 1 blocks
是编译器或 valgrind 中的错误。这段代码没有问题,因为我已经 运行 "hello world" 但它仍然说同样的话。
您未能初始化 ArithmeticExpression::isValue
。
ArithmeticExpression::ArithmeticExpression(std::string expr, bool isTopExpr) {
this->isTopExpr = isTopExpr;
int opIndex = findOpIndex(expr);
resultStr = expr;
if (opIndex == -1 || (opIndex == -1 && expr[0] == '-' && expr[1] != '(')) {
isValue = true;
arithExpr = NULL;
} else {
isValue = false; // add this line
std::string leftExpr = expr.substr(0, opIndex);
std::string rightExpr = expr.substr(opIndex+1, expr.length());
arithExpr = new Addition(leftExpr, rightExpr);
}
}
此外,我认为访问 expr[expr.length()]
不好,您应该更改
for (unsigned int c=expr.length(); c>0; c--) {
在Expression.cpp
到
for (unsigned int c=expr.length()-1; c>0; c--) {