C ++相同的对象,每次都有不同的结果

时间:2015-12-13 08:19:05

标签: c++ dynamic-memory-allocation object-oriented-analysis

以下是我项目的可运行片段。它假设是一个计算器,但我已经将它简化为尽可能简单,同时仍然表现出错误并且功能正常。

我为此代码:(的格式错误,样式和其他所有错误道歉。有些只是为了节省空间,就像空行一样。

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

ArithmeticExpression.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;
}

ArithmeticExpression.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 << ")";
}      

我的时候输出

((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”,它仍然说同样的事情。

1 个答案:

答案 0 :(得分:2)

您未能初始化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--) {