C++ – Null toewijzen aan een std::string

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::stringis 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 NULLof 0niet 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 NULLof een geldige tekenreeks zijn, terwijl C++ std::strings 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 0is van het type inten je kunt intniet 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 nullptrmet 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 valuealleen toegewezen aan mValuewanneer valuegeeneen null-pointer is. In alle andere gevallen (d.w.z. wanneer valueisnull), zal mValueeen 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 elsegeval is onnodig, wanneer u een stringobject 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::stringbewaren 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.

Other episodes