动态内存分配和输入(流)运算符C ++

时间:2017-04-13 20:58:55

标签: c++ operator-overloading allocation

我一直在研究一些学校问题而且我在operator>>处理内存分配,但是看到了不同的解决方案,所以我对此感到困惑.. operator>>效果很好当编译并提供良好的输出,但我不明白为什么,这里是代码.. (为什么我在代码下方感到困惑)

class Some
    {
    protected:
        char *name;
        int price;
        int anything;
    public:
        Some(const char *name="", const int anything=0, const int price=0)
        {
            this->name=new char[strlen(name)+1];
            strcpy(this->name, name);
            this->anything = anything;
            this->price=price;
        }
        ~Some() { delete [] name; }
        friend istream &operator>>(istream &in, Some &i)
        {
            return in>>i.name>>i.anything>>i.price;
        }
        void print(){
           cout << name << " " << anything << " " << price; 
        }
    };

主要

int main() {
    // your code goes here
    Some n;
    cin >> n;
    n.print();
    return 0;
}

所以使用Some n我们创建了一个对象,但是构造函数只为1个字符分配了内存,如果我错了(并设置了一些默认值)则纠正我。之后我们使用>> operator输入类型为Some的对象,但是只为name分配了一个char,我们可以根据需要输入。这是带有一些输入Compiled Code的编译版本。我的思维错在哪里?或者不应该这样做。谢谢!!

P.s我们不允许使用将负责分配的库..

2 个答案:

答案 0 :(得分:2)

缓冲区溢出(当你为单个std::cin >> i.name分配空间时,你正在做的事情,但是通过调用name来写得更好)被认为是未定义的行为C ++。这意味着编译器可以做任何响应它的事情,甚至是看似无关或疯狂的东西。

在实践中,这意味着有时,您的代码将完美运行,没有任何问题....直到您转移到不同的编译器或测试在不同的一天或具有不同的类型那天早上的咖啡,此时代码断了。 应该正在发生的事情是你的代码应该抛出由此代码产生的分段错误(或在Windows中,一个访问冲突),但我的猜测(我想强调这是一个< em> guess )是负责分配std::vector<char>的OS级别调用是从内存页面的早期获取内存,而对未分配内存的写入是在内存页面的其余部分中找到有效空间。

显然,你不应该依赖这种行为。根据您的帖子,您不允许使用std::string或(明显正确的选择)class Some { protected: std::string name; int price; int anything; public: //Passing by value means an optimization opportunity. We can move-construct name //instead of copying it. Some(std::string name = "", const int anything=0, const int price=0) : //We'll use a member-initialization list to initialize everything. Saves space //and saves a few CPU cycles as well! name(std::move(name)), anything(anything), price(price) {} //We don't need to declare the destructor anymore, because name's memory is automatically //managed! //~Some() {} //this code doesn't need to change. friend std::istream &operator>>(std::istream &in, Some &i) { return in >> i.name >> i.anything >> i.price; } //This doesn't technically *need* to change, but we can do better. //void print(){ //cout << name << " " << anything << " " << price; //} friend std::ostream & operator<<(std::ostream & out, Some const& i) { out << i.name << ' ' << i.anything << ' ' << i.price; } }; 等自动内存分配方案。这可能是因为你的教授<罢工>是一个教你可怕的设计原则的白痴,因为他们是一个多年来已经离开这个行业并且还没有赶上的老态傻瓜。如何使用现代C ++并打算教授试图教你如何进行手动内存分配。 出于某种无聊的原因。因此,您需要编写代码来处理这个问题。

Paul Mckenzie在评论中提到的文件(here)是一个良好的开端。第3页是相关代码。

或者,如果你的教授突然爆发了理智改变了主意,那么更正后的代码将如下所示:

form = CommentForm(
        instance=Comment(
            school=self.object, user=self.request.user.profile
        )
    )
    context['form'] = form

答案 1 :(得分:1)

你正在思考这个问题。

问题的解决方案包括将字符串的长度写入输出文件,然后写入字符串的字符。

说你有对象:

name = "First Last"
price = 15
anything = 0

编写对象时,您需要:

10 First Last 0 15

在文件中。

它为您提供了有关该对象的足够信息,以便您从文件中读回它。

istream &operator>>(istream &in, Some &i)
{
    size_t len;

    // Read the length of name
    in >> len;

    // Allocate memory for name.
    char* name = new char[len+1];

    // Read the name.
    // Discard the whitespace first.
    in.ignore();
    in.read(name, len);

    // Now read anything and price
    in >> i.anything >> i.price;

    // Release memory held by i.name before using memory allocated
    // in this function
    delete [] i.name;
    i.name = name;

    return in;
}

Some类型的对象写入文件的函数必须镜像函数以从文件中读回它。

std::ostream& operator<<(std::ostream& out, Some const& i)
{
    out << strlen(i.name) << " ";
    out.write(i.name, strlen(i.name);
    return out << " " << i.anything << " " << i.price        
}