Ich versuche zu wissen, ob a mit a in C ++ 17 prvalue
identisch ist. temporary
Betrachten Sie das folgende Beispiel,
//C++17 example
#include <iostream>
struct Custom
{
Custom()
{
std::cout<<"default constructor called"<<std::endl;
}
Custom(const Custom& var)
{
std::cout<<"copy constructor called"<<std::endl;
}
~Custom()
{
std::cout<<"destructor called"<<std::endl;
}
};
Custom func()
{
Custom temp;
return temp;//this will use copy constructor
}
int main() {
func();
}
Unter der Annahme, dass der obige Code mit -fno-elide-constructors
aktivierten Optionen ausgeführt wird, lautet meine Frage, ob der Prvalue, der als Kopie des temp
in der Funktion benannten lokalen Objekts erstellt func
wird, mit einem temporären in C++17 identisch ist.
Ich habe gelesen, dass in C++17 ein Prvalue kein Objekt ist. Hier sagt zum Beispiel der Benutzer das
"Prvalues sind keine Objekte (seit C++17)".
Ähnlich sagt hier der Benutzer
"Vor C++17 war der Prvalue bereits das Temporäre, worauf sich Ihr Zitat bezieht. Seit C++17 ist der Prvalue selbst kein Temporär..."
Aber das hat mich verwirrt, denn wenn ein Prvalue kein Objekt ist, was ist es dann? Ich meine, im obigen Beispiel temp
wird eine Kopie von mit dem Kopierkonstruktor erstellt. Jetzt, vor C++17, ist diese Kopie ein temporäres Objekt, das ein Prvalue ist. Aber was ändert sich in C++17. Ich denke, dass wir immer noch einen Prvalue haben, der mit dem Kopierkonstruktor erstellt wird, und dass Prvalue in C++17 temporär ist, da er für eine begrenzte Dauer existiert.
PS: Ich kann falsch beschreiben, was tatsächlich passiert, also korrigieren Sie mich bitte, indem Sie erklären, was in C++17 passiert und wie es sich von C++14 unterscheidet. Ich frage auch, weil ich in SO-Beiträgen (ähnliche Beiträge) gelesen habe, dass im obigen Beispiel keine vorübergehende Beteiligung an C ++ 17 vorliegt, was ich nicht verstehe, wie dies möglich ist.
Lösung des Problems
Aber das hat mich verwirrt, denn wenn ein Prvalue kein Objekt ist, was ist es dann?
Ein Ausdruck, der zu einem Objekt werden kann.
Ich denke, dass wir immer noch einen Prvalue haben, der mit dem Kopierkonstruktor erstellt wird, und dass Prvalue in C++17 temporär ist, da er für eine begrenzte Dauer existiert.
Der Prvalue ist noch kein Objekt (oder hier anders gedacht ).
Lassen Sie uns Ihr Beispiel erweitern, indem Sie etwas verwenden func
, um etwas zu initialisieren.
int main() {
auto obj = func();
}
obj
in main
und temp
in func
sind "dasselbe Objekt". Es ist, als wäre func
es stattdessen
void func(Custom * result) {
Custom & temp = *new(result) Custom;
}
int main() {
char storage[sizeof(Custom)];
Custom & obj = *reinterpret_cast<Custom *>(storage);
func(&obj);
obj.~Custom();
}
Oder beim -fno-elide-constructors
Belassen der Kopie von temp
in den Rückgabewert:
void func(Custom * result) {
Custom temp;
new(result) Custom(temp);
}
Was sich zwischen C++14 zu C++17 geändert hat, ist, dass anstatt einer zulässigen Abweichung vom Verhalten der abstrakten Maschine die Definition der abstrakten Maschine geändert wurde, um dieses Verhalten aufzuweisen.
Keine Kommentare:
Kommentar veröffentlichen