• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Referencja vs Const Referencja

Object Storage Arubacloud
+2 głosów
1,239 wizyt
pytanie zadane 15 lipca 2017 w C i C++ przez Bondrusiek Maniak (61,370 p.)

Witam,

stworzyłem taki przykładowy kod

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


int main ()
{
    string var = "hello world";
    string& ref = "hello world";
    const string& const_ref = "hello world";


    int var1 = 1;
    int& ref1 = 1;
    const int& const_ref1 = 1;
    return 0;
}

Przy referencji pojawiają się błędy. Natomiast przy const referencji brak jest błędu. Oto komunikaty

1)Przy string

 invalid initialization of non-const reference of type 'std::string& {aka std::basic_string<char>&}' from an rvalue of type 'const char*'
     string& ref = "hello world";
                   ^

2)Przy int

 invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'
     int& ref1 = 1;
                 ^

Nie rozumiem czemu można użyć z const a bez modyfikatora zwraca błąd. Na moje wyczucie dzieje się tak gdyż z definicji adres referencji można przypisać tylko raz. Kompilator tworzy z literału obiekt(fragment pamięci, który może przechowywać dane) lecz nie potrafi się do niego odwołać. Dodając modyfikator const zmienna staje się de facto tylko do odczytu i kompilator potrafi wyświetlić ten literał. Natomiast bez const zmienna ref jest modyfikowalna ale nie jest możliwe odwołanie się to fragmentu pamięci i zmienienie wartości stąd kompilator zwraca błąd. Sam to wydedukowałem stąd wysoce prawdopodobne, że się mylę. Czekam na wasze sugestie, uwagi, odpowiedzi.

Pozdrawiam,

3
komentarz 15 lipca 2017 przez adrian17 Ekspert (345,160 p.)

Niestety, trudno mi na to odpowiedzieć poza "tak jest zdefiniowane". Ogólnie Twoja dedukcja jest całkiem niezła. Można powiedzieć, że `const` jest wymagane, bo trudno powiedzieć co taki kod bez `const` by robił:

void f(int &x) { x += 1; }
int main(){
  f(1); // co jest zwiekszane o 1?
}

Może jeszcze to pomoże: https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

 

komentarz 18 sierpnia 2017 przez criss Mędrzec (172,590 p.)
Właściwie to twój komentarz, adrian, powinien być odpowiedzią :D IMO najlepiej tłumaczy pytanie autora.

3 odpowiedzi

+4 głosów
odpowiedź 18 sierpnia 2017 przez mokrowski Mędrzec (155,460 p.)
edycja 18 sierpnia 2017 przez mokrowski
Masz do czynienia z dwoma rodzajami wartości w C++. Jest to L-wartość (to co masz po lewej stronie znaku "=") i R-wartość (to co masz po prawej stronie znaku "="). R-wartości są z definicji tymczasowe (takie masz w przykładzie). Powstają na czas wykonania a następnie są przypisywane. Z kolei referencja ma w obowiązku zawsze wskazywać na istniejący obiekt w trakcie przypisania. Stąd jeśli konstruując string (po prawej stronie "=") z napisu przypisujesz ją do nie-stałej referencji, łamiesz regułę języka bo nie powinno się mieć referencji do obiektu który właśnie został zniszczony (co nie znaczy że nie ma "dzikich konstrukcji" które to umożliwią). Kompilator może to łatwo wykryć i ... wykrywa :-)

Jeśli referencja jest stała, następuje wydłużenie czasu jej życia i stąd udaje się przypisać obiekt.

W praktyce od C++14 obowiązuje optymalizacja takich przypisań (Copy elision) ale reguła obowiązuje jak gdyby to było literalne uruchamianie konstruktorów i operatorów przypisania/konstruktorów kopiujących.
komentarz 18 sierpnia 2017 przez criss Mędrzec (172,590 p.)
edycja 23 sierpnia 2017 przez criss
1
komentarz 18 sierpnia 2017 przez Evelek Nałogowiec (28,960 p.)

Jest to L-wartość (to co masz po prawej stronie znaku "=")

mokrowski, you know. wink 

komentarz 18 sierpnia 2017 przez mokrowski Mędrzec (155,460 p.)
@Evelek thx fixed.. :-)
+1 głos
odpowiedź 15 lipca 2017 przez j23 Mędrzec (194,920 p.)

const powoduje, że zmienna jest inaczej traktowana przez kompilator. W przypadku const int& zmienna wcale nie musi być tworzona w pamięci, jej wartość będzie użyta bezpośrednio w kodzie, czyli:

const int &i  = 666;

cout << i << '\n';

zostanie zredukowane do:

cout << 666 << '\n';

W typów grubszego kalibru, takich jak np. string, zmienna może być tworzona w oddzielnym segmencie pamięci (oczywiście nie będzie to już referencja, tylko normalna zmienna tylko-do-odczytu).

 

komentarz 15 lipca 2017 przez adrian17 Ekspert (345,160 p.)

W przypadku const int& zmienna wcale nie musi być tworzona w pamięci, jej wartość będzie użyta bezpośrednio w kodzie, czyli:

Nie ma związku, to tylko optymalizacja. Zwykłe `int i` też by to zrobiło. To nie wyjaśnia też

int f();
int main(){
  int& x = f(); // error
  const int& x = f(); // OK
}

string, zmienna może być tworzona w oddzielnym segmencie pamięci

Jest normalną zmienną na stosie.

komentarz 15 lipca 2017 przez j23 Mędrzec (194,920 p.)

Zwykłe `int i` też by to zrobiło.

Przy bardziej złożonym kodzie nie zrobiłoby. Na tym właśnie polega różnica między zmienną a stałą.

To nie wyjaśnia też (...)

Generalnie do zwykłej referencji nie możesz przypisać r-wartości z powodów, o których pisał OP - albo wartość nie ma adresu, albo adres jest tymczasowy.

Jest normalną zmienną na stosie.

To jest oczywiście kwestia tego, jak to sobie kompilator zrealizuje w kodzie wynikowym. Podejrzałem, jak to wygląda w VC. Nigdzie w mainie nie ma konstruowania obiektu string, a co za tym idzie, nie ma także jego niszczenia (wersja release ofcoz).

+1 głos
odpowiedź 18 sierpnia 2017 przez Evelek Nałogowiec (28,960 p.)
const string &str = "plain text";
string &&str = "plain text";

Są to równoważne zmienne z tą różnicą, że jedna z nich jest const oraz ma nieco inne właściwości.

komentarz 18 sierpnia 2017 przez draghan VIP (106,230 p.)

Są to równoważne zmienne z tą różnicą, że jedna z nich jest const oraz ma nieco inne właściwości.

To brzmi trochę jak "są takie same ale inne". ;)

I mówiąc szczerze, nie widzę większego sensu w tej odpowiedzi w kontekście zadanego pytania.

komentarz 18 sierpnia 2017 przez Evelek Nałogowiec (28,960 p.)

No to nie wiem jak Ci mogę pomóc draghan. frown const string& jest w pewnym stopniu powiązane z string&&, więc jak najbardziej warto o tym wspomnieć w KONTEKŚCIE tego pytania.

komentarz 18 sierpnia 2017 przez draghan VIP (106,230 p.)

const string& jest w pewnym stopniu powiązane z string&&

I znów: "w pewnym stopniu"... Widzisz, o co mi chodzi? ;)

komentarz 18 sierpnia 2017 przez Evelek Nałogowiec (28,960 p.)

O konkrety? Nie podam ich, bo nie mam notatek ze sobą. cheeky

komentarz 18 sierpnia 2017 przez Bondrusiek Maniak (61,370 p.)

BTW.

string &&str = "plain text";

Jak takie wyrażenie nazwać? Referencja adresu str wskazująca na "..." czy adres referencji wskazująca na "...". Wiesz który operator ma większy priorytet operator pobrania adresu czy operator referencji.

string &(&str) = "simple text";

Przy takiej konstrukcji kompilator wyrzuca mi błąd.

komentarz 18 sierpnia 2017 przez Evelek Nałogowiec (28,960 p.)
Referencja do r-wartości.

Podobne pytania

0 głosów
2 odpowiedzi 641 wizyt
pytanie zadane 21 lutego 2018 w C i C++ przez Hiskiel Pasjonat (22,830 p.)
0 głosów
1 odpowiedź 603 wizyt
pytanie zadane 19 grudnia 2018 w C i C++ przez kamyk2 Początkujący (420 p.)
0 głosów
2 odpowiedzi 830 wizyt
pytanie zadane 15 listopada 2016 w C i C++ przez timrh Mądrala (6,030 p.)

92,589 zapytań

141,439 odpowiedzi

319,694 komentarzy

61,974 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...