Cpp string :: copy функция добавляет дополнительные символы - PullRequest
0 голосов
/ 17 ноября 2018

Я использую функцию string :: copy в своем конструкторе копирования (глубокое копирование), и когда я использую его, он добавляет некоторые не значащие символы в мою строку. Вот моя основная функция:

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

int main(){


    MusicAlbum msc("a7x","Seize the day",2005);

    cout << msc.getMusicAlbumArtist()   <<endl;
    cout << msc.getMusicAlbumTitle()    <<endl;
    cout << msc.getMusicAlbumYear()     <<endl;

    MusicAlbum msc2(msc);
    cout << msc2.getMusicAlbumArtist()   <<endl;
    cout << msc2.getMusicAlbumTitle()    <<endl;
    cout << msc2.getMusicAlbumYear()     <<endl;
    //MusicAlbum msc3(msc);

    return 0;
}

странным моментом является то, что когда я пишу a7x ​​вместо Avenged семь раз в заголовок, он не добавляет символы.

Вот заголовок SimpleMusicAlbum.h:

#ifndef __SIMPLE_MUSIC_ALBUM_H
#define __SIMPLE_MUSIC_ALBUM_H
#include <string>
using namespace std;
class MusicAlbum {
 public:
    MusicAlbum(const string maArtist = "",
    const string maTitle = "",
    const int maYear = 0);

    ~MusicAlbum();
    MusicAlbum(const MusicAlbum &maToCopy);

    void operator=(const MusicAlbum &right);

    string getMusicAlbumArtist();
    string getMusicAlbumTitle();
    int getMusicAlbumYear();
 private:
    string artist;
    string title;
    int year;
};
#endif

Вот SimpleMusicAlbum.cpp:

MusicAlbum::MusicAlbum(const string maArtist,
            const string maTitle,
            const int maYear){
    artist = maArtist;
    title = maTitle;
    year = maYear;

}
//the problem is here
MusicAlbum::MusicAlbum(const MusicAlbum &maToCopy){
    char artistTemp[maToCopy.artist.size()] ;
    char titleTemp[maToCopy.title.size()];

    cout << maToCopy.artist.size() << endl;

    maToCopy.artist.copy(artistTemp, maToCopy.artist.size(), 0);
    artist = artistTemp;
    maToCopy.title.copy(titleTemp,maToCopy.title.size(),0);
    title = titleTemp;
    this->year = maToCopy.year;
}

//same problem occurs here
void MusicAlbum::operator=(const MusicAlbum &right){
    char artistTemp[right.artist.size()];
    char titleTemp[right.title.size()];
    right.artist.copy(artistTemp, right.artist.size(), 0);
    artist = artistTemp;
    right.title.copy(titleTemp,right.title.size(),0);
    title = titleTemp;
    this->year = right.year;
}
//destructor
MusicAlbum::~MusicAlbum(){
    // no allocation, no destruction.
}
//methods
string MusicAlbum::getMusicAlbumArtist() {
    return artist;
}

string MusicAlbum::getMusicAlbumTitle(){
    return title;
}

int MusicAlbum::getMusicAlbumYear(){
    return year;
}

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

Давайте разберем класс MusicAlbum только для его переменных-членов:

class MusicAlbum 
{
    //...
    string artist;
    string title;
    int year;
};

Учитывая, что это переменные-члены, создание копий MusicAlbum совершенно безопасно для выполнения , если у вас естькомпилятор делает копии .Таким образом, нет необходимости предоставлять пользовательский конструктор копирования и оператор присваивания.std::string имеет правильную семантику копирования из коробки, а int, очевидно, безопасно для копирования.Таким образом, это простое решение:

удалить эти функции из вашего класса .

Если, однако, MusicAlbum содержит указатели на динамически распределенную память или ресурсы, которые необходимо обработатьили какой-то другой аспект, который реализация компилятора по умолчанию конструктора копирования и оператора присваивания не предоставит правильно, тогда да, вы бы написали определяемый пользователем конструктор копирования / оператор присваивания.


Итак, что можетпроизойдет, если вы предоставите функции конструктора копирования и оператора присваивания, когда вам не нужно их предоставлять?

Единственные результаты:

  1. Вы написали эти функции правильно.
  2. Вы написали эти функции неправильно.

Можно подумать, что вариант 1. будет в порядке.Возможно, но недостатком является то, что вы, возможно, написали свою версию неэффективно (скорее всего, вы сделали).Копия / назначение по умолчанию компилятора всегда будет работать правильно и была бы написана эффективно.

Что касается опции 2., это то, что происходит с вашим кодом.Вместо того, чтобы отлаживать, просто удалите эти функции.Если вы должны были отладить и заставить эти функции работать правильно, вы попадаете обратно в пункт 1 в списке.Таким образом, вы действительно ничего не получили, кроме нескольких минут или часов написания и отладки функций, которые вам не нужно было писать в первую очередь.

Так что не тратьте свое время на написание функций, которые компилятор ужеобеспечивает для вас.Учитывая переменные-члены в вашем классе, компилятор всегда будет делать копии правильно.

0 голосов
/ 17 ноября 2018

Стандартные контейнеры библиотеки имеют свои собственные функции копирования и назначения. Нет необходимости копировать их вручную.

 MusicAlbum::MusicAlbum(const MusicAlbum    &maToCopy)
 {
     artist  = maToCopy.getMusicAlbumArtist();
     title = maToCopy.getMusicAlbumTitle();
     year = maToCopy.getMusicAlbumYear();   
 }

Вот рабочий пример.

 #include<string>
 #include<iostream>

 using namespace std;

 class MusicAlbum
 {
     public:
      MusicAlbum(string Artist, string Title, int Year):artist(Artist),
      title(Title),
      year(Year)
      {}
      string getTitle(){ return title; }
      string getArtist() { return artist; }
      int getYear() { return year; }
 private:
     string artist;
     string title;
     int year;  
 };

 int main()
 {
     MusicAlbum a{"a7x","albumname",2007};
         MusicAlbum b = a;
         cout << b.getArtist() << " " << b.getTitle() << " " <<   b.getYear() << endl;
 }
...