C ++:当临时std :: map超出范围时,将释放std :: map的项目

问题描述 投票:-1回答:1

我不是C ++非用户,我只是在尝试一些有趣的事情,被卡住了,我想我做错了。

我有我自己的类的std::mapstd::map<MyClass*, MyClass*>),我试图过滤出一个子集,将其存储为临时(本地实例)std::map<MyClass*, MyClass*>。问题是,当临时映射超出范围时,将调用MyClass上的析构函数,并将这些项释放。

我在做什么错?

编辑:同时添加了DictionaryMyString类:


#include <iostream>
#include "Dictionary.h"

Dictionary::Dictionary(const char *filename) {
    entries = new std::map<MyString *, MyString *>();
    load(filename);
}

void Dictionary::load(const char *filename) {
    FILE *fh = fopen(filename, "r");
    if (!fh) {
        printf("Unable to open file: %s\n", filename);
        return;
    }

    size_t len;
    while (!feof(fh)) {
        char *line = fgetln(fh, &len);
        if (len > 60) {
            printf("Line too long, skipping.\n");
            continue;
        }

        // find ";" character and change it to \0
        char *delimiter = strstr(line, ";");
        if (delimiter == nullptr) {
            printf("Line does not contain delimiter.\n");
            continue;
        }

        // if last character in line is newline, subtract length
        if (line[len - 1] == '\n') {
            len--;
        }

        entries->insert(std::pair<MyString *, MyString *>(
                new MyString(line, (size_t) (delimiter - line)),
                new MyString(delimiter + 1, (size_t) (len - (delimiter - line + 1)))));
    }

    fclose(fh);
}

void Dictionary::list(ComparisonOperations op, MyString *sub) {
    std::map<MyString *, MyString *> results;

    for (auto &entry : *entries) {
        switch (op) {
            case StartingOp:
                if (entry.first->beginsWith(*sub)) {
                    results.insert(entry);
                }
                break;
            case ContainingOp:
                if (entry.first->contains(*sub)) {
                    results.insert(entry);
                }
                break;
            case EndingOp:
                if (entry.first->endsWith(*sub)) {
                    results.insert(entry);
                }
                break;
        }
    }

    // print results
    Dictionary::print(std::cout, results);
}

void Dictionary::print(std::ostream &os, std::map<MyString *, MyString *> &results) {
    if (results.empty()) {
        os << "No match found." << std::endl;
    } else if (results.size() == 1) {
        auto result = results.begin();
        os << (MyString) *(result->first)
           << " => " << (MyString) *(result->second) << std::endl;
    } else {
        for (auto &result : results) {
             os << (MyString) *(result.first) << std::endl;
        }
    }
}

---

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include "MyString.h"

MyString::MyString() {
    buffer = (char *) malloc(1);
    memset(buffer, 0, 1);
}

MyString::MyString(const char *str) {
    buffer = (char *) malloc(MAX_MY_STRING_LEN + 1);
    memset(buffer, 0, MAX_MY_STRING_LEN + 1);
    strncpy(buffer, str, MAX_MY_STRING_LEN);
}

MyString::MyString(const char *str, int len) {
    buffer = (char *) malloc(len + 1);
    memset(buffer, 0, len + 1);
    strncpy(buffer, str, len);
}

MyString::~MyString() {
    if (buffer != nullptr) {
        printf("dealloc string %s!", buffer);
        free(buffer);
    }
    buffer = nullptr;
}

bool MyString::operator==(const MyString &cmp) const {
    return strcmp(buffer, cmp.buffer) == 0;
}

bool MyString::operator<(const MyString &cmp) const {
    return strcmp(buffer, cmp.buffer) < 0;
}

bool MyString::beginsWith(const MyString &sub) const {
    return strstr(buffer, sub.buffer) == buffer;
}

bool MyString::contains(const MyString &sub) const {
    return strstr(buffer, sub.buffer) != nullptr;
}

bool MyString::endsWith(const MyString &sub) const {
    char *pos = strstr(buffer, sub.buffer);
    return (pos - buffer + strlen(sub.buffer)) == strlen(buffer);
}

void MyString::print() {
    printf("%s\n", buffer);
}

std::ostream &operator<<(std::ostream &os, const MyString &str) {
    return os << ((const char *) str.buffer);
}


[PS:不,这不是我的学校作业,它实际上是朋友的学校作业,我正在尝试它只是为了好玩,因为,正如您所看到的,我的C ++太生锈了。

c++ destructor stdmap
1个回答
0
投票

由于MyString没有副本构造函数,(MyString) *(result->first)中的表达式Dictionary::print创建了一个临时实例,该临时实例借用了对基础数据的引用,然后过早将其从原始所有者下释放了。

© www.soinside.com 2019 - 2024. All rights reserved.