Como evitar explicitamente chamar um construtor ao passar objeto temporário por referência em C ++?
-
06-07-2019 - |
Pergunta
Vamos dizer que eu tenho uma classe:
class String
{
public:
String(char *str);
};
E duas funções:
void DoSomethingByVal(String Str);
void DoSomethingByRef(String &Str);
Se eu chamar DoSomethingByVal assim:
DoSomethingByVal("My string");
os números do compilador fora que ele deve criar um objeto String temporário e chamar o char * construtor.
No entanto, se eu tento usar DoSomethingByRef da mesma forma, eu recebo um "Não é possível converter parâmetro de 'char *' para 'String &'" erro.
Em vez disso, eu tenho que criar explicitamente uma instância:
DoSomethingByRef(String("My string"));
que pode ficar preety irritante.
Existe alguma maneira de evitar isso?
Solução
Você precisa passar por referência const:
Para:
void DoSomethingByVal(String Str);
Nesta situação, o compilador primeiro cria uma variável temporária. Então, a variável temporário é cópia construído no parâmetro.
Para:
void DoSomethingByRef(String const& Str);
Nesta situação, o compilador cria uma variável temporária. Mas variáveis ??temporárias não pode ser vinculado a uma referência que só pode ser vinculado a uma referência const para que a sua função original não pode ser chamado. Observe o std :: string objetos construtor recebe uma referência const é o parâmetro para o construtor de cópia e é por isso que a primeira versão funciona como o temporário é ligado ao parâmetro de referência const do construtor de cópia única.
Outras dicas
Hmm, eu não tenho certeza se
void DoSomethingByRef(String &Str);
DoSomethingByRef(String("My string"));
seria realmente compilar. Um rvalue não pode ligar-se a uma referência a não-const (porque um ref para não-const está declarando que você vai modificar o valor, e não faria sentido para modificar um temporário). Tem certeza de que não está fazendo:
String str("My string");
DoSomethingByRef(str);
Se você quiser DoSomethingByVal tomar um rvalue, o parâmetro tem de ser uma referência para const:
void DoSomethingByRef(const String &Str);
Marca:
DoSomethingByRef (const string & str);
"My String" não é uma String, que é um c-corda, um char *, se você quiser. Você precisa colocar isso c-string em um objeto String, e então você pode passar o novo objeto String por referência.
Outro ponto, você já está passando um char * ... isso é muito leve, apenas um ponteiro. Por que se preocupar com a passagem de um novo objeto por referência? Apenas alocar um novo objeto dentro daquele construtor da pilha e copiar o c-corda para ele.