Ik ben C++ zelf aan het leren. Ik heb de volgende code, maar hij geeft een foutmelding.
#include <iostream>
#include <string>
using namespace std;
int setvalue(const char * value)
{
string mValue;
if(value!=0)
{
mValue=value;
}
else
{
mValue=0;
}
}
int main ()
{
const char* value = 0;
setvalue(value);
cin.get();
return 0;
}
Dus ik wil een functie maken die char-pointers accepteert en ik wil er een pointer aan doorgeven. De functie wijst de aanwijzer toe aan zijn lidvariabele. Ik geef opzettelijk een null-pointer door. Hieronder volgt de foutmelding die ik krijg:
D:\CPP\TestCP.cpp In function `int setvalue(const char*)':
note C:\Dev-Cpp\include\c++\3.4.2\bits\basic_string.h:422 candidates are: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
note C:\Dev-Cpp\include\c++\3.4.2\bits\basic_string.h:422 std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const _CharT*) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
note C:\Dev-Cpp\include\c++\3.4.2\bits\basic_string.h:422 std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(_CharT) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
het is eigenlijk klagen over regel: mValue=0;
Waarom klaagt het over deze regel? Ik kan geen null toewijzen aan een tekenreeks?
Antwoord 1, autoriteit 100%
Ik kan geen null toewijzen aan een tekenreeks?
Nee. std::string
is geen aanwijzertype; het kan niet “null” worden gemaakt. Het kan niet de afwezigheid van een waarde vertegenwoordigen, wat een null-pointer wordt gebruikt om aan te geven.
Het kan leegworden gemaakt door er een lege string aan toe te wijzen (s = ""
of s = std::string()
) of door het te wissen (s.clear()
).
Antwoord 2, autoriteit 24%
U kunt NULL
of 0
niet toewijzen aan een C++ std::string
-object, omdat het object geen aanwijzer is. Dit is een belangrijk verschil met snaren in C-stijl; een tekenreeks in C-stijl kan NULL
of een geldige tekenreeks zijn, terwijl C++ std::string
s altijd een bepaalde waarde opslaan.
Er is geen gemakkelijke oplossing hiervoor. Als u een schildwachtwaarde wilt reserveren (bijvoorbeeld de lege tekenreeks), kunt u zoiets doen als
const std::string NOT_A_STRING = "";
mValue = NOT_A_STRING;
U kunt ook een aanwijzer naar een tekenreeks opslaan, zodat u deze op null kunt instellen:
std::string* mValue = NULL;
if (value) {
mValue = new std::string(value);
}
Hopelijk helpt dit!
Antwoord 3, autoriteit 9%
Letterlijke 0
is van het type int
en je kunt int
niet toewijzen aan std::string
. Gebruik mValue.clear()
of wijs een lege string toe mValue=""
.
Antwoord 4, autoriteit 7%
Ik zal niet beweren dat het een goedidee is (of de semantiek van het gebruik van nullptr
met dingen die geen pointerszijn), maar het is relatief eenvoudig om een klasse te maken die “nullable“-semantiek biedt (zie nullable_string).
Dit past echter veel beter bij C++17’s std:: optional:
#include <string>
#include <iostream>
#include <optional>
// optional can be used as the return type of a factory that may fail
std::optional<std::string> create(bool b)
{
if (b)
return "Godzilla";
else
return {};
}
int main()
{
std::cout << "create(false) returned "
<< create(false).value_or("empty") << std::endl;
// optional-returning factory functions are usable as conditions of while and if
if (auto str = create(true))
{
std::cout << "create(true) returned " << *str << std::endl;
}
}
std::optional
, zoals weergegeven in het voorbeeld, kan worden omgezet in bool
, of u kunt de methode has_value()
gebruiken, heeft uitzonderingen voor slechte toegang, enz. Dit biedt u semantiek met nulwaarden, wat lijkt te zijn wat Mariaprobeerde te bereiken.
En als je niet wilt wachten op C++17-compatibiliteit, bekijk dit antwoord over Boost.Optional.
Antwoord 5, autoriteit 4%
Er zijn twee methoden om te overwegen die hetzelfde effect bereiken voor het omgaan met null-pointers naar C-stijl strings.
De ternaire operator
void setvalue(const char *value)
{
std::string mValue = value ? value : "";
}
of het bescheiden if-statement
void setvalue(const char *value)
{
std::string mValue;
if(value) mValue = value;
}
In beide gevallen wordt value
alleen toegewezen aan mValue
wanneer value
geeneen null-pointer is. In alle andere gevallen (d.w.z. wanneer value
isnull), zal mValue
een lege tekenreeks bevatten.
De ternaire operatormethode kan handig zijn voor het leveren van een alternatieve standaardtekenreeks in de afwezigheid van een waarde uit value
:
std::string mValue = value ? value : "(NULL)";
Antwoord 6
Het else
geval is onnodig, wanneer u een string
object maakt, is het standaard leeg.
Antwoord 7
Veel C API’s gebruiken een null-pointer om “gebruik de standaard” aan te geven, b.v. mosquittopp. Dit is het patroon dat ik gebruik, gebaseerd op David Cormack‘s antwoord:
mosqpp::tls_set(
MqttOptions->CAFile.length() > 0 ? MqttOptions->CAFile.c_str() : NULL,
MqttOptions->CAPath.length() > 0 ? MqttOptions->CAPath.c_str() : NULL,
MqttOptions->CertFile.length() > 0 ? MqttOptions->CertFile.c_str() : NULL,
MqttOptions->KeyFile.length() > 0 ? MqttOptions->KeyFile.c_str() : NULL
);
Het is een beetje omslachtig, maar je kunt alles als een std::string
bewaren tot de API-aanroep zelf.
Antwoord 8
compiler geeft een fout omdat bij het toewijzen van mValue=0 compiler toewijzingsoperator=(int ) voor compileertijdbinding wordt gevonden, maar het is niet aanwezig in de tekenreeksklasse.
als we cast volgende instructie naar char typen zoals mValue=(char)0, dan is het compileren succesvol omdat string class de operator=(char) methode bevat.