理解类对象[关闭]

Posted

技术标签:

【中文标题】理解类对象[关闭]【英文标题】:Understanding class object [closed] 【发布时间】:2019-06-21 12:50:55 【问题描述】:

我正在尝试创建将使用指针存储在向量内的对象

当我不使用指针时,我可以将对象存储在向量中,但是当我尝试使用指针时,我不能这样做

// created class that combine some attributes for file "datum" = date,     "vrijeme" = creation of file etc.

class datoteka
    public:
      string datum;
      string vrijeme;
      string velicina;
      string ime;

    datoteka();
    datoteka(string datum, string vrijeme, string velicina, string ime)

    
        this -> datum = datum;
        this -> vrijeme = vrijeme;
        this -> velicina = velicina;
        this -> ime = ime;
    

    ~datoteka();
;


int main()

    vector <datoteka> fajlovi;

    string linija;
    string prva;
    int i = 0;
    datoteka * pokObjDatoteke;
    pokObjDatoteke = new datoteka();

    std::ifstream pisi("list.txt"); //file is open 

    while(getline(pisi,linija)) //get first line of file 
    
        string vrijednost; 
        stringstream red;  //create stream from line 
        string datoteka[4]; // create array to store seperate information
        red << linija; 
        while(!red.eof() && i != 4) // since line containt lot of tabs i                          
                                    read just first for values
        
            red >> vrijednost;
            datoteka[i]= vrijednost;
            i++;
            cout << vrijednost << " ovo je vrijednost" << endl;
        
        pokObjDatoteke->datum = datoteka[0];
        pokObjDatoteke->vrijeme = datoteka[1];
        pokObjDatoteke->velicina = datoteka[2];
        pokObjDatoteke->ime = datoteka[3];

        fajlovi.push_back(*pokObjDatoteke);  /**** problem ****
    

    return 0;

我想将对象存储在向量中,而不是我只获得一些内存位置,可能来自指针,但我如何存储对象而不是地址

【问题讨论】:

“不能那样做”和“问题”是什么意思?你期望什么结果,你观察到什么不同的结果?我看不出这段代码有什么致命的错误。虽然没有必要将 pokObjDatoteke 设为指针并在堆上分配它,但它几乎是无害的(您确实会泄漏一个 datoteka 对象)。 别再乱搞new(和delete)了。只需使用datoteka pokObjDatoteke;。我看不出你为什么需要一个指针。 您的代码过于复杂。本地的string datoteka[4]; 是不必要的,您可以直接阅读pokObjDatoteke-&gt;datum 等。出于风格和可读性的问题,我不会将变量命名为类型。我什至不知道这是可能的。 另一件事是原则上您应该在程序中使用英文名称。英语是 IT 界的通用语——每个人都理解ptr 前缀,但不是每个人都理解pok。正如您现在所看到的,我们在说同一种边缘语言的孤立人群中工作的时代已经结束。 (如果每个人都使用 7 位 ASCII 和英语,世界会变得更美好,但没人听我的话。) 什么是“问题”?您是否观察到编译错误?运行时错误? 【参考方案1】:

这个:

fajlovi.push_back(*pokObjDatoteke);

pokObjDatoteke 指向的对象的副本 存储在向量中。指向的对象随后会被泄露,因为您永远不会删除它。

你真的需要这里的指针吗?您的向量包含值类型,而不是指针,因此只需使用 emplace_back 直接在向量中构造您的对象:

while (getline(pisi, linija))

    string vrijednost; 
    stringstream red;
    string datoteka[4];
    red << linija; 
    while (!red.eof() && i != 4) 
        red >> vrijednost;
        datoteka[i]= vrijednost;
        i++;
        cout << vrijednost << " ovo je vrijednost" << endl;
    
    fajlovi.emplace_back(datoteka[0], datoteka[1], datoteka[2],
                         datoteka[3]);

但是,如果您真的想要向量中的指针,则将其声明为:

vector <datoteka*> fajlovi;

然后将原始代码中的 push_back 调用更改为:

fajlovi.push_back(pokObjDatoteke);

这会将指针推入向量中。你需要记得在vector被销毁时删除它们,否则所有对象都会被泄露:

for (auto* obj : fajlovi) 
    delete obj;

像这样的手动内存管理容易出错且令人头疼。不要这样做。请改用智能指针,例如shared_ptr。删除原始代码中的这些行:

vector <datoteka> fajlovi;

// ...

datoteka * pokObjDatoteke;
pokObjDatoteke = new datoteka();

并将它们替换为:

#include <memory>
// ...

vector <shared_ptr<datoteka>> fajlovi;
// ...

auto pokObjDatoteke = make_shared<datoteka>();

然后push_back 与:

fajlovi.push_back(pokObjDatoteke);

无需致电newdelete

但是,看起来您根本不需要指针。您可以只使用此答案开头所示的值类型。

【讨论】:

请支持我,但请允许我指出,在当代标准操作系统中,main 中分配的对象不会泄漏。操作系统只是在程序退出时回收程序的内存(由main 返回触发)。在 main 末尾删除将没有任何好处;特别是,程序既不能使用它(除非静态析构函数需要比其运行状态更多的内存)和操作系统(因为通常 C++ 运行时不会将释放的内存返回给操作系统)。如果有的话,释放具有教育价值,但不释放根本不会在任何有意义的意义上泄漏。【参考方案2】:

如果你想存储对象,那你为什么要使用指针呢?

datoteka pokObjDatoteke;

while (...)

    ...
    pokObjDatoteke.datum = datoteka[0];
    pokObjDatoteke.vrijeme = datoteka[1];
    pokObjDatoteke.velicina = datoteka[2];
    pokObjDatoteke.ime = datoteka[3];

    fajlovi.push_back(pokObjDatoteke);

当你说不使用指针有效时,你为什么要尝试使用指针?

【讨论】:

您的建议可能会更好;但是 OP 的错误在哪里? @PeterA.Schneider 如果 OP 有一个错误(我认为这并不完全清楚,他可能只是有一个误解),那么一如既往,它在他没有的代码中发布。 那么这并不能回答问题。【参考方案3】:

虽然 OP 没有披露输入文件的示例,但这一行(除了其他答案中指出的所有问题外)似乎很可疑

while(!red.eof() && i != 4) ...

参见例如Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?

更好的模式是执行提取并然后检查它是否成功。

while( some_stream >> some_data ) ...

OP 的代码可以改写成这样的

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>

class datum

    std::string a_, b_, c_, d_;
public:
    datum() = default;
    datum(std::string const &a, std::string const &b, std::string const &c, std::string const &d)
        : a_(a), b_(b), c_(c), d_(d)
    

    friend std::istream &operator>> (std::istream &is, datum &obj)
    
        return is >> obj.a_ >> obj.b_ >> obj.c_ >> obj.d_;
    
    friend std::ostream &operator<< (std::ostream &os, datum const &obj)
    
        return os << "a: '" << obj.a_ << "', b: '"<< obj.b_
                  << "', c: '" << obj.c_ << "', d: '" << obj.d_ << '\'';
    
;

int main()

    std::vector<datum> data;
    std::ifstream in_stream "list.txt";
    if ( !in_stream )
    
        std::cout << "Error: unable to open input file.\n";
        return -1;
    

    std::string line, junk;
    while(getline(in_stream, line))
    
        // This won't consider an error to have empty lines in the file 
        if (line.empty())
            continue;

        std::istringstream iss(line);
        datum dd;
        iss >> dd;
        // Stops if there are more or less strings than required in the line
        if ( !iss  or iss >> junk)
            break;
        data.push_back(std::move(dd));
    

    for (auto const & d : data)
        std::cout << d << '\n';

可测试here。

【讨论】:

以上是关于理解类对象[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

同一类的一个对象如何在 c++ 中分配给同一类的另一个对象? [关闭]

工厂类[关闭]

使用对象 ID 与将对象填充到其他类之间的权衡是啥? [关闭]

Java - 创建类关闭时是否会破坏对象引用?

面向对象的理解 和 类

将字符串转换为类对象 [关闭]