Как реализовать operator = () для класса, имеющего ссылочную переменную-член? - PullRequest
3 голосов
/ 04 февраля 2012

Я хочу иметь объект, который содержит ссылку, и поместить этот объект в вектор ...

Должен ли я использовать интеллектуальные указатели вместо ссылок на элементы в любом объекте, который я хочу вставить в вектор? Это было то, что я хотел сделать:

#include <string>
#include <vector>
using namespace std;

class MyClass {
   public:
    MyClass(const string& str_ref);    //constructor
        MyClass(const MyClass& mc);        //copy constructor
   private:
        string& my_str;
};

MyClass::MyClass(const string& str_ref) :
    my_str(str_ref)
{}

MyClass::MyClass(const MyClass& mc) :
    my_str(mc.my_str)
{}


int main() {

    //create obj and pass in reference
    string s = "hello";
    MyClass my_cls(s);

    //put into vector
    vector<MyClass> vec;
    vec.push_back(my_cls);

    return 0;
}

//Throws Error
//ref.cpp:6:7: error: non-static reference member ‘std::string& MyClass::my_str’, can’t use default assignment operator

Однако в нем говорится, что мне нужно реализовать свой собственный оператор = (), поскольку сгенерированный по умолчанию оператор недопустим, но, разумеется, законного способа сделать это ...

#include <string>
#include <vector>
using namespace std;

class MyClass {
   public:
    MyClass(const string& str_ref);    //constructor
        MyClass(const MyClass& mc);        //copy constructor

        MyClass operator=(const MyClass& mc);      //operator =

   private:
        string& my_str;
};

MyClass::MyClass(const string& str_ref) :
    my_str(str_ref)
{}

MyClass::MyClass(const MyClass& mc) :
    my_str(mc.my_str)
{}

//not a constructor. should not construct new object
//and return that?
MyClass MyClass::operator=(const MyClass& mc) {
   if (this != &mc) {                 //test for self-assignment.
    my_str(mc.my_str);            //can't reseat refs. this shouldn't work.
   }

   return *this;
}

int main() {

    //create obj and pass in reference
    string s = "hello";
    MyClass my_cls(s);

    //put into vector
    vector<MyClass> vec;
    vec.push_back(my_cls);

    return 0;
}

//THROWS:
//ref2.cpp: In constructor ‘MyClass::MyClass(const string&)’:
//ref2.cpp:18:19: error: invalid initialization of reference of type ‘std::string& {aka //std::basic_string<char>&}’ from expression of type ‘const string {aka const //std::basic_string<char>}’
//ref2.cpp: In member function ‘MyClass MyClass::operator=(const MyClass&)’:
//ref2.cpp:29:18: error: no match for call to ‘(std::string {aka std::basic_string<char>}) //(std::string&)’

Значит, я вынужден использовать умный указатель здесь или что-то кроме ссылки?

РЕДАКТИРОВАТЬ: Это упрощение. String & - это не передаваемый объект, а более сложный объект, содержащий векторный объект.

Ответы [ 3 ]

6 голосов
/ 04 февраля 2012

Вы можете хранить указатель raw вместо ссылки здесь.Необработанные указатели могут быть переустановлены, и поэтому они являются хорошим способом эмулировать перезаписываемые ссылки в C ++.

class MyClass
{
public:
  MyClass(const string& str_ref);
  MyClass(const MyClass& mc);
  // by the way, operator= should return a reference
  MyClass& operator=(const MyClass& mc);
private:
  string* my_str;
};

Таким образом, operator= будет подпоркой для реализации.

5 голосов
/ 04 февраля 2012

Как насчет использования std::reference_wrapper<T>? Теперь вы не обязаны реорганизовывать свой код, чтобы использовать умный указатель, но вы также не используете внутренний указатель, чтобы кто-то мог прийти позже и подумать, что он должен delete.

class MyClass 
{
   public:
      MyClass(string &str_ref)
         : my_str(std::ref(str_ref))
      {
      }

   private:
      std::reference_wrapper<std::string> my_str;
};
0 голосов
/ 07 сентября 2012

Если вы хотите иметь возможность использовать оператор присваивания вашего участника (т. Е. std::string& operator=(std::string const&)), вы не можете использовать иное превосходное предложение std::reference_wrapper. Но вы можете перестроить свой объект с нуля, используя конструктор копирования, так что ваш член может на самом деле быть необработанной ссылкой:

MyClass& MyClass::operator=(MyClass const& from) {
  this->~MyClass();
  new(this) MyClass(from);
  return *this;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...