繁体   English   中英

为什么初始化第二个对象会修改我的第一个对象?

[英]Why initializing a second object does modify my first object?

我有一个类 IStream2:

class IStream2 {
   private:
      char* fn;
   public:
      IStream2(char* filename);
      char* get_filename();
};


IStream2::IStream2(char *filename) {
   strcpy(fn, filename);
}
char * IStream2::get_filename() {
   return fn;
}

这是主要代码:

vector<IStream2> istreams;

char fn[] = "file1.txt";
IStream2 reader2 = IStream2(fn);
istreams.push_back(reader2);

char fn2[] = "file2.txt";
IStream2 reader3 = IStream2(fn2);
istreams.push_back(reader3);
cout << istreams[0].get_filename() << endl;

它打印 file2.txt 但我期望 file1.txt。 我知道我应该使用字符串,但我想解决这个问题。

IStream2::IStream2(char *filename) {
   strcpy(fn, filename);
}

不为fn分配存储空间。 strcpy(fn, filename); 调用写入任何存储fn指向的未定义行为,然后所有赌注都关闭。 该程序可以做任何事情。

正确答案是使用std::string

class IStream2 {
private:
    std::string fn;
public:
    IStream2(const char* filename); // note const. if not modifying a passed rference, 
                                    // mark it const. The compiler can make optimizations 
                                    // and can catch mistakes for you
                                    // also the function can now receive string literals
    const char* get_filename(); // another const this is because a string won't 
                                // easily give you a non const pointer
}; <-- note the added ;

IStream2::IStream2(const char *filename): fn(filename) {
}
const char * IStream2::get_filename() {
   return fn.c_str(); // get the char array from the string
}

但我怀疑这是用 Classes 编写 C 的练习,所以我们回到石器时代。 这需要做更多的工作,因为我们必须自己管理所有内存。 例如,我们需要遵守三定律。 三分法则是什么?

叹。

class IStream2 {
private:
    char* fn;
public:
    IStream2(const char* filename); // note const char *
    ~IStream2(); // need destructor to clean up fn. This means we need to
                 // comply with the Rule of Three
    IStream2(const IStream2 & src); // copy constructor
    IStream2 & operator=(IStream2 src); // assignment operator
    char* get_filename(); // Note: by returning a non const pointer here we
                          // allow the caller to tamper with the contents of 
                          // fn and even delete it. This defeats the point 
                          // of declaring fn private, so avoid doing this.
};

IStream2::IStream2(const char *filename) {
   fn = new char[strlen(filename) +1]; // allocate storage. 
                                       // The +1 is to hold the string's NULL terminator
   strcpy(fn, filename);
}
// implement copy constructor
IStream2::IStream2(const IStream2 & src) {
   fn = new char[strlen(src.fn) +1];
   strcpy(fn, src.fn);
}
// implement destructor
IStream2::~IStream2()
{
    delete[] fn;
}
// implement assignment operator. Using Copy And Swap Idiom 
IStream2 & IStream2::operator=(IStream2 src)
{
    std::swap(fn, src.fn);
    return *this;
}
char * IStream2::get_filename() {
   return fn;
}


int main()
{
    vector<IStream2> istreams;

    const char* fn = "file1.txt"; // note const char *. string literals may be
                                  // read-only memory and can't be changed
    IStream2 reader2 = IStream2(fn);
    istreams.push_back(reader2);

    const char* fn2 = "file2.txt"; // and again const char *
    IStream2 reader3 = IStream2(fn2);
    istreams.push_back(reader3);
    cout << istreams[0].get_filename() << endl;
    return 0;
}

既然我们正在与恐龙搏斗,我不会打扰五分法则和移动操作,但是看看以错误的方式来做这件事有多烦人?

更多关于复制和交换习语

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM