Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

rvalue ref.

5 views
Skip to first unread message

Markus Donath

unread,
May 17, 2018, 7:20:04 AM5/17/18
to
Ich benötige eine Fuktion, die einen Parameter einmal als const
reference und einmal als rvalue reference hat:

void test(const t& x);
void test(t&& x);

Die Funktionen würden exakt das gleiche tun. Ich möchte allerdings nicht
zweimal den gleichen Quelltext reinschreiben, daher habe ich das so gemacht:

void test(const t& x)
{
t x_(x);
test(std::forward<t>(x_);
}

Macht man das so oder gibt es was besseres?

Markus

Markus Schaaf

unread,
May 17, 2018, 9:00:04 AM5/17/18
to
Am 17.05.2018 um 08:41 schrieb Markus Donath:

> void test(const t& x);
> void test(t&& x);
>
> Die Funktionen würden exakt das gleiche tun. Ich möchte allerdings nicht
> zweimal den gleichen Quelltext reinschreiben, daher habe ich das so
> gemacht:
>
> void test(const t& x)
> {
>   t x_(x);
>   test(std::forward<t>(x_);
> }
>
> Macht man das so oder gibt es was besseres?

Wäre es nicht anders herum besser? Spart die Kopie. Außer der
Algorithmus braucht die. (Dann erübrigt sich jedoch die Frage.)

MfG

Florian Weimer

unread,
May 17, 2018, 5:10:04 PM5/17/18
to
* Markus Donath:

> Ich benötige eine Fuktion, die einen Parameter einmal als const
> reference und einmal als rvalue reference hat:
>
> void test(const t& x);
> void test(t&& x);
>
> Die Funktionen würden exakt das gleiche tun.

Bis auf daß an passender Stelle Copy- bzw.
Move-Assignment/Construction vorgenommen wird?

In diesem Fall solltest Du eine Funktion

void test(t x);

schreiben und an geeigneter Stelle std::move(x) verwenden.

Die getrennten Overloads skalieren nicht mit einer wachsenden Zahl von
Parametern.

Stefan Reuther

unread,
May 18, 2018, 1:40:04 PM5/18/18
to
Hi,

Am 17.05.2018 um 08:41 schrieb Markus Donath:
> Ich benötige eine Fuktion, die einen Parameter einmal als const
> reference und einmal als rvalue reference hat:
>
> void test(const t& x);
> void test(t&& x);
>
> Die Funktionen würden exakt das gleiche tun.

Mir ist gerade nicht eingängig, wie die Funktionen tatsächlich genau das
gleiche tun können wollen. Die erste soll doch das Objekt unverändert
lassen, während die zweite Dinge aus dem Objekt heraus moven können
soll. Das mag zwar im Quelltext dann gleich aussehen, macht aber was
anderes.

> void test(const t& x)
> {
> t x_(x);
> test(std::forward<t>(x_);
> }
>
> Macht man das so oder gibt es was besseres?

Mir fehlt ja schon seit geraumer Zeit ein

template<qualifier Q> void test(Q t& x);

für diesen und andere Zwecke.


Stefan

Markus Donath

unread,
May 24, 2018, 5:00:05 AM5/24/18
to
On 05/18/2018 07:24 PM, Stefan Reuther wrote:
>
> Mir ist gerade nicht eingängig, wie die Funktionen tatsächlich genau das
> gleiche tun können wollen. Die erste soll doch das Objekt unverändert
> lassen, während die zweite Dinge aus dem Objekt heraus moven können
> soll. Das mag zwar im Quelltext dann gleich aussehen, macht aber was
> anderes.
>

Beide Funktionen woolen das übergebene Objekt nicht verändern, aber bei
der rvalue-Variante kann ggf. eine Zwischenkopie gespart werden:

vector<int> v1;
...
test(v1); // Aufruf von test(const vector<int>&)

vector<int> add(const vector<int>& v1, const vector<int> v2);
test(add(v1, v2)); // Aufruf von test(vector<int>&&)

Hätte ich die rvalue-Variante nicht, würde auch für den 2. Aufruf die
const-ref-Variante benutzt. Dies macht aber eine Kopie von add(v1, v2),
die aber eigentlich nicht benötigt wird, oder?

>
> Mir fehlt ja schon seit geraumer Zeit ein
>
> template<qualifier Q> void test(Q t& x);
>
> für diesen und andere Zwecke.

Verstehe ich leider nicht.

>
>
> Stefan
>

Markus

Adriaan van Oosten

unread,
May 24, 2018, 10:40:04 AM5/24/18
to
Am 24.05.2018 um 10:15 schrieb Markus Donath:
> On 05/18/2018 07:24 PM, Stefan Reuther wrote:
>>
>> Mir ist gerade nicht eingängig, wie die Funktionen tatsächlich genau das
>> gleiche tun können wollen. Die erste soll doch das Objekt unverändert
>> lassen, während die zweite Dinge aus dem Objekt heraus moven können
>> soll. Das mag zwar im Quelltext dann gleich aussehen, macht aber was
>> anderes.
>>
>
> Beide Funktionen woolen das übergebene Objekt nicht verändern, aber bei
> der rvalue-Variante kann ggf. eine Zwischenkopie gespart werden:
>
> vector<int> v1;
> ...
> test(v1); // Aufruf von test(const vector<int>&)
>
> vector<int> add(const vector<int>& v1, const vector<int> v2);
> test(add(v1, v2)); // Aufruf von test(vector<int>&&)
>
> Hätte ich die rvalue-Variante nicht, würde auch für den 2. Aufruf die
> const-ref-Variante benutzt. Dies macht aber eine Kopie von add(v1, v2),
> die aber eigentlich nicht benötigt wird, oder?
>

Du machst gerade Annahmen darüber wie dein Compiler den von Dir
geschriebenen Code (möglicherweise) umsetzt, um dann vermeintliche
"Optimierungen" einzusetzen. Meiner Erfahrung nach ist das kein guter
Programmier-Stil, erschwert die Wartbarkeit und erhöht die Komplexität
unnötig.

Sowas sollte nur passieren wenn es UNBEDINGT nötig ist.

Benutze die Sprache so, wie diese es vorsieht um etwas zu erledigen.

Wenn Du das Objekt nicht ändern willst würd ich einen "call by value"
anstatt einer "call by reference" vorschlagen.

>>
>> Mir fehlt ja schon seit geraumer Zeit ein
>>
>>     template<qualifier Q> void test(Q t& x);
>>
>> für diesen und andere Zwecke.
>
> Verstehe ich leider nicht.
>
>>
>>
>>    Stefan
>>
>
> Markus

Adriaan


---
Diese E-Mail wurde von Avast Antivirus-Software auf Viren geprüft.
https://www.avast.com/antivirus

Florian Weimer

unread,
May 24, 2018, 1:50:06 PM5/24/18
to
* Markus Donath:

> Hätte ich die rvalue-Variante nicht, würde auch für den 2. Aufruf die
> const-ref-Variante benutzt. Dies macht aber eine Kopie von add(v1, v2),
> die aber eigentlich nicht benötigt wird, oder?

Nein, Referenzen machen keine Kopien. Wenn const T & ausreichend ist,
bring T && nichts. Anders ist es, wenn die aufgerufene Funktion selbst
eine Kope macht, dann kann T && plus std::move diese tatsächlich
vermeiden. Aber wie ich schon schrieb: Man sollte in diesem Fall
trotzdem nur eine Funktion schreiben, eben mit T als Argumenttyp.

Stefan Reuther

unread,
May 24, 2018, 2:00:22 PM5/24/18
to
Am 24.05.2018 um 10:15 schrieb Markus Donath:
> On 05/18/2018 07:24 PM, Stefan Reuther wrote:
>> Mir ist gerade nicht eingängig, wie die Funktionen tatsächlich genau das
>> gleiche tun können wollen. Die erste soll doch das Objekt unverändert
>> lassen, während die zweite Dinge aus dem Objekt heraus moven können
>> soll. Das mag zwar im Quelltext dann gleich aussehen, macht aber was
>> anderes.
>
> Beide Funktionen woolen das übergebene Objekt nicht verändern, aber bei
> der rvalue-Variante kann ggf. eine Zwischenkopie gespart werden:
>
> vector<int> v1;
> ...
> test(v1); // Aufruf von test(const vector<int>&)
>
> vector<int> add(const vector<int>& v1, const vector<int> v2);
> test(add(v1, v2)); // Aufruf von test(vector<int>&&)
>
> Hätte ich die rvalue-Variante nicht, würde auch für den 2. Aufruf die
> const-ref-Variante benutzt. Dies macht aber eine Kopie von add(v1, v2),
> die aber eigentlich nicht benötigt wird, oder?

Nein, dann würde ein temporäres Objekt erzeugt mit dem Ergebnis von
'add(v1, v2)', die const-Referenz würde an dieses Objekt gebunden, und
nach dem Funktionsaufruf 'test' wird das Objekt zerstört.

Bei 'test(vector<int>&&)' passiert genau das gleiche, nur dass hier die
Funktion 'test' das übergebene Objekt plündern darf. Dadurch entsteht
erst die mögliche Ersparnis.

>> Mir fehlt ja schon seit geraumer Zeit ein
>>
>> template<qualifier Q> void test(Q t& x);
>>
>> für diesen und andere Zwecke.
>
> Verstehe ich leider nicht.

Ich habe halt öfter Funktionen, in denen das gleiche drinsteht, aber
verschiedener Objektcode erzeugt werden soll. Forwarder-Funktionen
("return m_foo.getX()") in const/nonconst, und eben Funktionen mit
plünderbaren Parametern ('T&&') oder konstanten ('const T&'). Außer
Makros hat C++ da nichts zu bieten, um die doppelte Schreibarbeit zu
vermeiden.


Stefan
0 new messages