Uniform initialization
-
Benutzt ihr uniform initialization und wenn ja to which extend?
ich versuche es einigermaßen konsequent, beispielsweise beim default-initialisieren von objecten
std::vector<int> v{}; int a{}; int *pa{nullptr}; auto spa{make_unique<int>()};
Ich mag, dass bei dieser Form kein gleichheitszeichen vorkommt und eine Verwechslung mit assingment ausgeschlossen ist.
Etwas nervig ist, dass durch die Verwendung von {} initializer-lists für objecte, welche diese unterstützten präferiert wird.
Das führt beispielsweise dazu, dass bei folgendem Code eine temporäre initialier-list erzeugt wird, dh. ein rvalue, der sich aber nur an ne lvalue-reference to const binden lässt. Eine rvalue-reference als return value funktionier hier irgendwie nicht
invalid initialization of reference of type ‘std::vector<int>&&’ from expression of type ‘<brace-enclosed initializer list>’
class A { std::vector<int> v{}; // in-class initialization public: const std::vector<int>& getValVec() const { return {v}; } ... };
SeppJ meinte in nem anderen Thread, dass man return values im Allgemeinen nicht const machen sollte.
Also wie verfahrt ihr bei solchen Fällen?
-
std::vector<int> v{}; int a{}; int *pa{nullptr}; auto spa{make_unique<int>()};
std::vector<int> v; int a = 0; int *pa = nullptr; auto spa = make_unique<int>();
Du bist wohl ein wenig übereifrig mit den geschweiften Klammern. Ich schlage vor, dass du sie einfach weglässt, außer wo sie zwingend notwendig sind. Das erübrigt auch diese konfusen Fragen:
Das führt beispielsweise dazu, dass bei folgendem Code eine temporäre initialier-list erzeugt wird, dh. ein rvalue, der sich aber nur an ne lvalue-reference to const binden lässt. Eine rvalue-reference als return value funktionier hier irgendwie nicht
Da wird keine "temporäre initializer-list" erzeugt. Der Compiler versucht einfach, die Referenz mit dem Inhalt der initializer-list zu initialisieren. Das schlägt fehl, weil du eine rvalue Referenz mit einem lvalue zu initialisieren versuchst.
-
Das Problem ist mir jetzt klar geworden:
durch das const auf dem this-pointer ist es unabdingbar hier bei dem return value ebenfalls const zu setzen.
Würde hier eine rvalue-referenz zusammen mit nem std::move des rückgabe Werts einen Vorteil bringen?
-
Sewing schrieb:
Würde hier eine rvalue-referenz zusammen mit nem std::move des rückgabe Werts einen Vorteil bringen?
Das wäre also ein Getter, den man pro Objekt jeweils einmal aufrufen kann?
Was versuchst du zu erreichen?
-
Sewing schrieb:
Benutzt ihr uniform initialization und wenn ja to which extend?
Nur da, wo es den Code leichter lesbar macht.
An =-Zeichen finde ich gar nichts falsch. Dein Code sähe bei mir so aus:
std::vector<int> v; auto a = 0; int *pa = nullptr; auto spa = make_unique<int>();
SeppJ meinte in nem anderen Thread, dass man return values im Allgemeinen nicht const machen sollte.
Das bezog sich auf einfache Typen wir int. Nicht auf Referenzen auf Objekte. Wenn ich ne const& auf ein internes Objekt zurückgeben (einfach nur
return v;
), dann ist die Frage, ob das unter Umständen nicht die Kapselung, die mit einer Klasse erreicht werden soll, wieder aufhebt.
-
Sewing schrieb:
Ich mag, dass bei dieser Form kein gleichheitszeichen vorkommt und eine Verwechslung mit assingment ausgeschlossen ist.
Ich mag nicht, dass bei dieser Form kein Gleichheitszeichen vorkommt und man optisch nicht einfach zwischen dem, was initialisiert wird, und dem Initialisierer unterscheiden kann - es ist alles nur ein großer Misthaufen, der durch Klammern am Auseinanderfallen gehindert wird. Es stinkt aber auch so schon genug.
Sewing schrieb:
Benutzt ihr uniform initialization und wenn ja to which extend?
Gar nicht. So etwas wie uniform initialization gibt es nicht in C++.
Die unterschiedlichen Formen der Initialisierung unterscheiden sich semantisch, und folglich kann kein Programm, dass sich sich alle diese verschiedenen Semantiken nutzen soll, stets nur der gleichen Initialisierungsform bedienen.
-
bei folgdendem Code bekomme ich einen Error
class Interface; class firstlist : public Interface; // soll nur bedeuten, dass diese Klassenhierarchie besteht... std::map<std::string, std::unique_ptr<Interface>> _lists {{"FirstList", std::make_unique<Firstlist>()}};
/usr/include/c++/4.9/ext/new_allocator.h:120:4: error: use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const std::basic_string<char>; _T2 = std::unique_ptr<ListInterface>]’ { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } ^ In file included from /usr/include/c++/4.9/bits/stl_algobase.h:64:0, from /usr/include/c++/4.9/vector:60, from ars300targets.h:2, from ars300Radar.h:7, from test.cpp:1: /usr/include/c++/4.9/bits/stl_pair.h:127:17: note: ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const std::basic_string<char>; _T2 = std::unique_ptr<ListInterface>]’ is implicitly deleted because the default definition would be ill-formed: constexpr pair(const pair&) = default; ^ /usr/include/c++/4.9/bits/stl_pair.h:127:17: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = ListInterface; _Dp = std::default_delete<ListInterface>]’ In file included from /usr/include/c++/4.9/memory:81:0, from radar.h:8, from ars300Radar.h:8, from test.cpp:1: /usr/include/c++/4.9/bits/unique_ptr.h:356:7: note: declared here unique_ptr(const unique_ptr&) = delete;
klar der copy constructor vom unique_ptr ist deleted, aber ich initialisiere hier doch. Es scheint irgendwie an der initializer List zu liegen.
Könnt ihr mir helfen?
-
Von http://en.cppreference.com/w/cpp/utility/initializer_list. Hervorhebung von mir.
The underlying array is a temporary array of type const T[N], in which each element is copy-initialized (except that narrowing conversions are invalid) from the corresponding element of the original initializer list. The lifetime of the underlying array is the same as any other temporary object, except that initializing an initializer_list object from the array extends the lifetime of the array exactly like binding a reference to a temporary (with the same exceptions, such as for initializing a non-static class member). The underlying array may be allocated in read-only memory.
Das heißt, wenn du eine initializer_list verwenden möchtest, müssen deine Objekte Copy-constructable sein. Das ist ein unique_ptr aber nicht.