Как избежать явного вызова конструктора при передаче временного объекта по ссылке в C++?
-
06-07-2019 - |
Вопрос
Допустим, у меня есть класс:
class String
{
public:
String(char *str);
};
И две функции:
void DoSomethingByVal(String Str);
void DoSomethingByRef(String &Str);
Если я вызову DoSomethingByVal следующим образом:
DoSomethingByVal("My string");
компилятор определяет, что он должен создать временный объект String и вызвать конструктор char*.
Однако, если я попытаюсь использовать DoSomethingByRef таким же образом, я получу ошибку «Невозможно преобразовать параметр из 'char *' в 'String &'».
Вместо этого мне нужно явно создать экземпляр:
DoSomethingByRef(String("My string"));
что может сильно раздражать.
Есть ли способ избежать этого?
Решение
Вам нужно передать константную ссылку:
Для:
void DoSomethingByVal(String Str);
В этой ситуации компилятор сначала создает временную переменную.Затем временная переменная копируется в параметр.
Для:
void DoSomethingByRef(String const& Str);
В этой ситуации компилятор создает временную переменную.Но временные переменные не могут быть привязаны к ссылке, они могут быть привязаны только к константной ссылке, поэтому исходную функцию нельзя вызвать.Обратите внимание, что конструктор объектов std::string принимает константную ссылку - это параметр конструктора копирования, и поэтому первая версия работает, поскольку временная версия привязана только к константному ссылочному параметру конструктора копирования.
Другие советы
Хм, я не уверен, если
void DoSomethingByRef(String &Str);
DoSomethingByRef(String("My string"));
на самом деле будет компилироваться. Значение r не может связываться со ссылкой на неконстантный (поскольку ссылка на неконстантный указывает, что вы измените значение, и не имеет смысла изменять временное значение). Вы уверены, что не делаете:
String str("My string");
DoSomethingByRef(str);
Если вы хотите, чтобы DoSomethingByVal принял значение r, параметр должен быть ссылкой на const:
void DoSomethingByRef(const String &Str);
Делать:
DoSomethingByRef(const String &str);
" Моя строка " это не строка, это c-строка, символ *, если хотите. Вам нужно поместить эту c-строку в объект String, а затем вы можете передать новый объект String по ссылке.
Еще один момент: вы уже передаете символ * ... он довольно легкий, просто указатель. Зачем беспокоиться о передаче нового объекта по ссылке? Просто выделите новый объект внутри этого конструктора из кучи и скопируйте в него строку c.