Подтвердить что ты не робот

Передача по ссылке на конструктор

Я решил посмотреть, будет ли назначение ссылки члену, сделав элемент ссылкой. Я написал следующий фрагмент, чтобы проверить его. Там есть простой класс Wrapper с std::string как переменная-член. Я беру a const string& в конструкторе и назначаю его переменной public member. Позже в методе main() я изменяю переменную-член, но string, переданный в конструктор, остается неизменным, как получилось? Я думаю, что в Java переменная изменилась бы, почему бы и нет в этом фрагменте кода? Как точно работают ссылки в этом случае?

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

class Wrapper
{
public:
   string str;

   Wrapper(const string& newStr)
   {
      str = newStr;
   }
};

int main (int argc, char * const argv[]) 
{
   string str = "hello";
   cout << str << endl;
   Wrapper wrapper(str);
   wrapper.str[0] = 'j'; // should change 'hello' to 'jello'
   cout << str << endl;
}
4b9b3361

Ответ 1

Чтобы назначить ссылку в конструкторе, вам нужно иметь ссылочный элемент

 class A{
     std::string& str;
 public:
     A(std::string& str_)
     :    str(str_) {} 
 };

str теперь ссылается на значение, которое вы передали. То же самое относится к const refs

 class A{
     const std::string& str;
 public:
     A(const std::string& str_)
     :    str(str_) {} 
 };

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

Ответ 2

class Wrapper
{
public:
   string& str;

   Wrapper(string& newStr) : str(newStr) {}
};

Обратите внимание: вы не можете принять const string& и сохранить его в string&, вы потеряете const-correctness при этом.

Ответ 3

Поскольку Wrapper::str не является ссылкой, это независимый объект. Поэтому, когда вы делаете str = newStr, вы копируете строку.

Ответ 4

Вам нужно использовать инициализатор и объявить str в качестве ссылки, как в:

class Wrapper {
public:
   string &str;

   Wrapper(string& newStr)
      : str(newStr) {
   }
};

Как вы его пишете, все, что вы делаете, это копирование значения ссылки, которую вы передаете в constuctor. Вы не сохраняете ссылку. Объявив ссылку как член класса и инициализируя ее ссылкой на другой экземпляр строки, вы получите поведение, которое вы ищете.

Ответ 5

Вы должны объявить Wrapper::str как string&, а не как string.

Ответ 6

Переменная основного тела std::string. Вы переменная параметра const std::string &. Константа в ссылках всегда "низкий уровень const" Это означает, что он изменяет тип объекта, а не фактический объект. Напротив, "верхний уровень const" изменяет фактический объект. Прочитайте С++ Primer на верхнем уровне const для уточнения.

Вот как выглядит ваше задание при передаче аргументов. const std::string & = std:: str;//Значения оммиты. i.e const std::string netStr = std::string str Вы инициализируете ссылку на const-тип с неконстантным значением, которое является приемлемым. Вы не должны изменять значение std::string str, используя эту ссылку. Попробуйте изменить значение конструктора newStr внутри. Вы получите ошибку компиляции Затем вы выполните другое задание. std::string= const std::string внутри конструктора, который также является приемлемым. Тот факт, что wrap.str [0] не изменил str main, заключается в том, что, хотя ссылка была использована для создания экземпляра класса str, класс str имеет свой собственный объект и не связан с главной str. Использование ссылки в параметре просто связывает этот параметр с главной str не main str с классом str. Если ваша переменная класса была ссылкой, она могла бы быть изменена.