C++ 理解类对象

C++ 理解类对象,c++,class,oop,object,C++,Class,Oop,Object,我试图创建一个对象,它将使用指针存储在向量中 当我不使用指针时,我可以将对象存储在向量中,但当我尝试使用指针时,我不能这样做 // created class that combine some attributes for file "datum" = date, "vrijeme" = creation of file etc. class datoteka{ public: string datum; string vrijeme; s

我试图创建一个对象,它将使用指针存储在向量中

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

// 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;
}
//创建的类组合了文件“datum”=日期、“vrijeme”=文件创建等的一些属性。
达托特卡级{
公众:
串基准;
字符串vrijeme;
丝绒;
字符串输入法;
达托特卡();
datoteka(字符串基准、字符串vrijeme、字符串velicina、字符串ime)
{
这个->基准=基准;
此->vrijeme=vrijeme;
这->velicina=velicina;
这个->输入法=输入法;
}
~datoteka();
};
int main()
{
fajlovi病媒;
里尼娅;
字符串prva;
int i=0;
达托特卡*pokObjDatoteke;
pokObjDatoteke=新的datoteka();
std::ifstream pisi(“list.txt”);//文件已打开
while(getline(pisi,linija))//获取文件的第一行
{
字符串vrijednost;
stringstream red;//从行创建流
字符串datoteka[4];//创建数组以存储单独的信息
红色>vrijednost;
datoteka[i]=vrijednost;
i++;
cout velicina=datoteka[2];
pokObjDatoteke->ime=datoteka[3];
fajlovi.向后推(*pokObjDatoteke);/****问题****
}
返回0;
}

我想将对象存储在向量中,而只是获取一些内存位置,可能来自指针,但如何存储对象而不是地址呢?如果要存储对象,为什么要使用指针

datoteka pokObjDatoteke;

while (...)
{
    ...
    pokObjDatoteke.datum = datoteka[0];
    pokObjDatoteke.vrijeme = datoteka[1];
    pokObjDatoteke.velicina = datoteka[2];
    pokObjDatoteke.ime = datoteka[3];

    fajlovi.push_back(pokObjDatoteke);
}
正如你所说,当不使用指针有效时,为什么要尝试使用指针?

这是:

fajlovi.push_back(*pokObjDatoteke);
存储向量中指向的对象的副本。指向的对象随后被泄漏,因为您从未删除它

你真的需要这里的指针吗?向量包含值类型,而不是指针,因此只需使用
emplace\u 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]);
}
这将把指针推入向量。当向量被销毁时,您需要记住删除它们,否则所有对象都将泄漏:

for (auto* obj : fajlovi) {
    delete obj;
}
像这样的手动内存管理很容易出错,而且令人头痛。不要这样做。使用智能指针,如
共享\u ptr
。删除原始代码中的以下行:

vector <datoteka> fajlovi;

// ...

datoteka * pokObjDatoteke;
pokObjDatoteke = new datoteka();
无需调用
new
delete


然而,再一次,看起来您根本不需要指针。您可以使用本答案开头所示的值类型。

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

while(!red.eof() && i != 4) {...}
见例

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

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';
}
#包括
#包括
#包括
#包括
#包括
类基准
{
std::字符串a、b、c、d;
公众:
datum()=默认值;
数据(标准:字符串常量a、标准:字符串常量b、标准:字符串常量c、标准:字符串常量d)
:a_(a),b_(b),c_(c),d_(d)
{}
friend std::istream&operator>>(std::istream&is、数据和obj)
{
返回值为>>对象a.>>对象b.>>对象c.>>对象d;
}

friend std::ostream&Operator你所说的“不能那样做”和“问题”是什么意思?你期望的结果是什么,你观察到的结果是什么?我看不出这段代码有什么致命的错误。虽然没有必要将
pokObjDatoteke
作为指针并在堆上分配它,但它基本上是无害的(您确实泄漏了一个
datoteka
对象)。停止乱搞
new
(和
delete
)。只需使用
datoteka pokObjDatoteke;
。我看不出任何需要指针的原因。您的代码不必要地复杂。本地
字符串datoteka[4]
是不必要的,你可以直接阅读
pokObjDatoteke->datum
等。就风格和可读性而言,我不会像类型那样命名变量。我甚至不知道这是可能的。另一件事是,作为原则,你应该在程序中使用英语名称。英语是其中的通用语言——每个人都理解nds是一个
ptr
前缀,但不是每个人都懂
pok
。我们在讲相同边缘语言的孤立人群中工作的时代已经结束了,正如你现在所看到的。(如果每个人都使用7位ASCII和英语,世界会更好,但没有人听我说。)“问题”是什么?您是否观察到编译错误?运行时错误?您的建议可能更好;但OP的错误在哪里?@PeterA.Schneider如果OP有错误(我不认为完全清楚,他可能只是有误解)然后,像往常一样,它出现在他没有发布的代码中。然后,这并不能回答问题。请允许我投票,但请允许我指出,在任何当代标准操作系统上,
main
中分配的对象都不会泄漏。当程序退出时,操作系统只会回收程序的内存(这是由从
main
返回触发的)在主结束时的删除将没有任何好处;特别是,程序都不能使用它(除非静态析构函数需要比运行状态更多的内存),也不需要OS(因为通常C++运行时不返回空闲的内存到OS)。.如果说有什么区别的话,自由有教育价值,但不是自由根本就没有任何意义。
fajlovi.push_back(pokObjDatoteke);
while(!red.eof() && i != 4) {...}
while( some_stream >> some_data ) {...}
#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';
}