Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

27.05.2013, 23:49

rhs references

Habe wohl die neuen rhs references noch nicht wirklich verstanden.

Folgendes Code Fragment kompiliert nicht, weil der Copy-Ctor aufgerufen wird:

C-/C++-Quelltext

1
void Class::foo(std::unique_ptr<OtherClass>&& bar){ stack.push(bar);}



bar ist doch eine Referenz auf ein temporäres Objekt, also müsste doch die entsprechende Version von push aufgerufen werden!?
Wenn ich einen neuen unique_ptr einfüge oder std::move verwende, funktioniert es.

E: Compiler ist VC10

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Rexona for men« (28.05.2013, 00:00)


H5::

Treue Seele

Beiträge: 368

Wohnort: Kiel

  • Private Nachricht senden

2

28.05.2013, 01:19

Also ich glaube du versuchst dir das Ganze etwas zu kompliziert zu denken. Die Move-Semantik macht eigentlich nichts anderes als zu Bewegen anstatt zu kopieren. Dafür gibt es ja auch die neuen Move-Konstruktoren usw.

Und genauso kannst du dir das auch vorstellen. Du nimmst etwas aus dem einen unique_ptr raus und tust es in den anderen rein. Aber genau das möchtest du ja erst bei push machen. D.h. dein Move muss erst dort stattfinden.

C-/C++-Quelltext

1
2
3
4
5
6
7
#include <stack>
auto Test( std::unique_ptr<int>& up )
    -> void
{
    std::stack<std::unique_ptr<int>> stack;
    stack.push( std::move( up ) );
}


Wenn du sie nicht schon kennst, eventuell hilft dir die Seite:
C++11 und die Sache mit der Move-Semantik

Was ich jetzt nicht nachgeschlagen habe ist, was VC100 alles unterstützt.

Anmerkung:
Ein rvalue ist alles was kein lvalue ist :D… Also alles was dir einen Fehler an den Kopf knallt wenn es links steht. Dein bar jedoch kann links stehen, deswegen ist es kein rvalue (zumindest im Block). std::move kann man sich in dem Fall etwas wie einen Cast von lvalue zum rvalue vorstellen so, das move anstatt copy Semantik verwendet wird.
:love: := Go;

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »H5::« (28.05.2013, 01:38)


3

28.05.2013, 02:17

Ok, was ich nicht bedacht habe, ist dass bar selber natürlich ein lvalue ist. Aber verweisen tut bar doch auf einen rvalue ?(
Und der Move-Ctor möchte doch genau so eine Referenz haben, oder nicht?
std::move gibt doch auch nur eine solche Referenz zurück. Muss diese denn auch ein rvalue sein, also die Referenz?

H5::

Treue Seele

Beiträge: 368

Wohnort: Kiel

  • Private Nachricht senden

4

28.05.2013, 02:24

Ich poste dir einfach mal einen Link, dass ist eventuell einfacher als wenn ich versuche das zu erklären ;).

Is an Rvalue Reference an Rvalue?

Edit: Da ich wach gehalten werde:
Du hast es aber schon richtig erkannt. Bar ist ein lvalue. Sprich eine rvalue Referenz ist eine Referenz auf einen rvalue, selbst aber ein lvalue. Und genau das ist der wichtige Unterschied. Der Move-CTor wird aufgerufen wenn ihm ein rvalue übergeben wird, um in ihm dann eine rvalue Referenz zu erhalten. Dadurch dass bar aber wie gesagt ein lvalue ist wird der Copy-CTor aufgerufen.
Ohman, das klingt total wirr aber eigentlich ist es ganz einfach :D

Rvalue Referenz == lvalue != rvalue
:love: := Go;

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »H5::« (28.05.2013, 03:31)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

28.05.2013, 08:32

Ok, was ich nicht bedacht habe, ist dass bar selber natürlich ein lvalue ist.

bingo

Aber verweisen tut bar doch auf einen rvalue ?(

Das ändert aber nix dran, dass es ein lvalue ist, auch wenn es auf ein rvalue verweist. Der Trick mit den rvalue references ist ja gerade, dass sie nur an rvalues gebunden werden können.

Und der Move-Ctor möchte doch genau so eine Referenz haben, oder nicht?

Der Move-Ctor möchte ein rvalue haben.

std::move gibt doch auch nur eine solche Referenz zurück. Muss diese denn auch ein rvalue sein, also die Referenz?

std::move() ist eine Funktion und Funktionsrückgabewerte sind rvalues, außer wenn sie lvalues sind (ok, im konkreten Fall handelt es sich genaugenommen um ein xvalue, das ist aber eine art von rvalue)... ;)

6

28.05.2013, 19:47

Ok, danke soweit für die Aufklärung und den netten Link.

Dann bedeutet eine rvalue reference also nur, dass das Objekt dahinter ein rvalue ist, d.h. außerhalb von foo keinen Namen hat
und ich es somit sicher bewegen kann, wofür ich aber std::move brauche, weil bar ja kein rvalue ist. Richtig?

H5::

Treue Seele

Beiträge: 368

Wohnort: Kiel

  • Private Nachricht senden

7

29.05.2013, 10:38

Wichtig ist, dass du die jeweiligen Dinge separat betrachtest. Move-Semantik, rvalue, rvalue Referenz. Es sind alles unterschiedliche Dinge, die aber erst zusammen Sinn ergeben. Ohne die rvalue referenz könnte man ja garnicht erkennen welche z.B. Konstruktorart man denn gerne benutzen würde. Trotz allem bleibt die rvalue-Referenz eben immer noch selbst ein lvalue. Um zu sagen das man Move-Semantig benutzen möchte für einen lvalue kann man z.B. std::move einsetzen. Usw.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stack>
#include <iostream>
auto Test( std::unique_ptr<int>& up )
    -> void
{
    std::cout << "lvalue" << std::endl;
    std::stack<std::unique_ptr<int>> stack;
    stack.push( std::move( up ) );
}

auto Test( std::unique_ptr<int>&& up )
    -> void
{
    std::cout << "rvalue" << std::endl;
    std::stack<std::unique_ptr<int>> stack;
    stack.push( std::move( up ) );
}

auto main( int argc, char** argv )
    -> int
{
    std::unique_ptr<int> lvalue( new int );

    Test( std::unique_ptr<int>( new int ) );
    Test( lvalue );

    return 0;
}
:love: := Go;

Werbeanzeige