問題タブ [move-semantics]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 異なるクラスからの移動コンストラクターを定義する必要がありますか?
次のことを考慮してください。
移動セマンティクスを最大限に活用するには、2番目のコンストラクターのようなコンストラクターを定義する必要がありますか?それとも、適切な状況で自動的に処理されますか?
c++ - fstream の移動を実装する C++0x ライブラリ
How to return an fstream (C++0x) への答えを見つけた後、fstreams の移動 (またはスワップ) を実装する現在の c++0x ライブラリがあるかどうか疑問に思っていました ( gcc (27.9)はそうではありません) 。 . それも無料ならいいのに。
または、値によって関数から fstreams に戻る他の方法はありますか?
私はlibcxxをコンパイルしようとしましたが、それは非常に linux/mac 固有のようで、コンパイルできない Solaris でも実行する必要があります。
この問題を回避することはできます (たとえば、参照によって戻る) が、呼び出し元のコードを変更する必要のない解決策がある場合に備えて、これを尋ねると思いました。
c++ - スワップをより速く、より使いやすく、例外に対して安全にする
昨夜は眠れず、考え始めましたstd::swap
。おなじみのC++98バージョンは次のとおりです。
ユーザー定義クラスFoo
が外部リソースを使用する場合、これは非効率的です。一般的なイディオムは、のメソッドvoid Foo::swap(Foo& other)
と特殊化を提供することですstd::swap<Foo>
。関数テンプレートを部分的に特殊化することはできず、名前空間での名前のオーバーロードは違法であるため、これはクラステンプレートでは機能しないことに注意してください。std
解決策は、自分の名前空間にテンプレート関数を記述し、引数に依存するルックアップに依存してそれを見つけることです。これは、クライアントが直接using std::swap
呼び出すのではなく、「イディオム」に従うかどうかに大きく依存しますstd::swap
。非常にもろい。
C ++ 0xではFoo
、ユーザー定義のムーブコンストラクターとムーブ代入演算子がある場合、カスタムswap
メソッドとstd::swap<Foo>
特殊化を提供してもstd::swap
、コピーの代わりに効率的なムーブを使用するため、パフォーマンス上の利点はほとんどありません。
もういじる必要がないことswap
は、プログラマーからすでに多くの負担を取り除きます。現在のコンパイラーはまだムーブコンストラクターとムーブ代入演算子を自動的に生成しませんが、私が知る限り、これは変更されます。残っている唯一の問題は例外安全性です。これは、一般に、移動操作がスローを許可されており、これによりワームの缶全体が開かれるためです。質問「移動したオブジェクトの状態は正確には何ですか?」物事をさらに複雑にします。
それから私は考えていました、std::swap
すべてがうまくいく場合、C ++ 0xのセマンティクスは正確には何ですか?スワップ前後のオブジェクトの状態はどうなっていますか?通常、移動操作によるスワッピングは外部リソースには影響せず、「フラットな」オブジェクト表現自体にのみ影響します。
swap
では、それを正確に実行するテンプレートを単純に作成してみませんか。オブジェクト表現を交換しますか?
これは、それが得るのと同じくらい効率的です:それは単に生のメモリを爆破します。ユーザーの介入は必要ありません。特別なスワップメソッドや移動操作を定義する必要はありません。これは、C ++ 98でも機能することを意味します(右辺値の参照はありません)。しかし、さらに重要なことは、スローが発生しないため、例外安全性の問題を忘れることができるということです。memcpy
このアプローチには2つの潜在的な問題があります。
まず、すべてのオブジェクトが交換されることを意図しているわけではありません。クラスデザイナがコピーコンストラクタまたはコピー代入演算子を非表示にした場合、クラスのオブジェクトを交換しようとすると、コンパイル時に失敗するはずです。タイプでコピーと割り当てが合法であるかどうかをチェックするデッドコードを簡単に紹介できます。
どんなまともなコンパイラでも、死んだコードを簡単に取り除くことができます。(「スワップ適合性」をチェックするためのより良い方法はおそらくありますが、それは重要ではありません。重要なのはそれが可能であるということです)。
次に、一部のタイプは、コピーコンストラクターおよびコピー割り当て演算子で「異常な」アクションを実行する場合があります。たとえば、変更をオブザーバーに通知する場合があります。このような種類のオブジェクトは、そもそもコピー操作を提供するべきではなかったので、これは小さな問題だと思います。
このスワッピングのアプローチについてどう思うか教えてください。それは実際に機能しますか?使ってみませんか?これが壊れてしまうライブラリの種類を特定できますか?追加の問題がありますか?議論!
c++ - C++11 の右辺値とムーブ セマンティクスの混乱 (return ステートメント)
C++ 11 の右辺値参照と移動セマンティクスを理解しようとしています。
これらの例の違いは何ですか? また、ベクトル コピーを実行しないのはどれですか?
最初の例
2 番目の例
3 番目の例
c++ - すでに RVO がある場合、ムーブ セマンティクスはどのような最適化を提供しますか?
私が理解している限り、移動セマンティクスを追加する目的の 1 つは、「一時的な」オブジェクトをコピーするための特別なコンストラクターを呼び出してコードを最適化することです。たとえば、この回答では、そのようなものを最適化するために使用できることがわかりますstring a = x + y
。x+y は右辺値式であるため、ディープ コピーの代わりに、文字列へのポインターと文字列のサイズのみをコピーできます。しかし、ご存知のように、最新のコンパイラは戻り値の最適化をサポートしているため、移動セマンティクスを使用しないと、コードはコピー コンストラクターをまったく呼び出しません。
それを証明するために、次のコードを書きます。
そして、最適化モードで VC++2010 と g++ で実行した後、空の出力が得られます。
それがなくてもコードがより速く動作する場合、それはどのような最適化ですか? 私の理解が間違っていることを説明していただけますか?
c++ - std :: forwardがconstexpr-nessを破棄するのはなぜですか?
宣言されていない場合constexpr
、std::forward
引数を転送する関数のconstexpr-nessは破棄されます。constexpr-nessを維持できるように、それ自体が宣言されていないのはなぜですか?std::forward
constexpr
例:(g++スナップショットでテスト済み-2011-02-19)
注:技術的には、std::forward
constexprを作成するのは簡単です。たとえば、次のようになります(gでは)std::forward
に置き換えられていることに注意してください。fix::forward
私の質問は:なぜstd::forward
のように定義されていないのfix::forward
ですか?
注2:この質問は、constexpr std :: tupleに関する他の質問とある程度関連しています。これは、cstrを右辺値で呼び出すことによって作成できない技術的な理由ですが、ここでの質問は明らかに(はるかに)より一般std::forward
的ですconstexpr
。std::tuple
c++11 - 右辺値を使用した算術式で「最適な」演算子のオーバーロード解決を実現するにはどうすればよいですか。
まず、過度に冗長な質問をお詫びします。問題を正確に要約する他の方法は考えられませんでした...次に実際の質問に移ります。
現在、C ++ 0x右辺値参照を実験しています...次のコードは、望ましくない動作を生成します。
結果は出力になります
結果を格納するための
新しい一時的なものを構築する結果を格納するために一時的な第1オペランドを 再利用
する結果を格納するために一時的な第1オペランドを再利用する結果を格納するための新しい一時的なものを構築する
私は次のようなものを望んでいましたが
constructing new temporary to store result
reusing temporary 1st operand to store result
reusing temporary 2nd operand to store result
reusing temporary 2nd operand to store result
After trying to re-enact what the compiler was doing (I'm using MinGW G++ 4.5.2 with option -std=c++0x in case it matters), it actually seems quite logical. The standard says that arithmetic operations of equal precedence are evaluated/grouped left-to-right (why I assumed right-to-left I don't know, I guess it's more intuitive to me). So what happened here is that the compiler evaluated the sub-expression (v3 + v4)
first (since it's in parentheses?), and then began matching the operations in the expression left-to-right against the operator overloads, resulting in a call to Vector4 operator + (const Vector4& other)
for the sub-expression v1 + v2
. If I want to avoid the unnecessary temporary, I'd have to make sure that no more than one lvalue operand appears to the immediate left of any parenthesized sub-expression, which is counter-intuitive to anyone using this "library" and innocently expecting optimal performance (as in minimizing the creation of temporaries).
(I'm aware that there's ambiguity in my code regarding operator + (Vector4&& v1, const Vector4& v2)
and operator + (Vector4&& other)
when (v3 + v4)
is to be added to the result of v1 + v2
, resulting in a warning. But it's harmless in my case and I don't want to add yet another overload for two rvalue reference operands - anyone know if there's a way to disable this warning in gcc?)
Long story short, my question boils down to: Is there any way or pattern (preferably compiler-independent) this vector class could be rewritten to enable arbitrary use of parentheses in expressions that still results in the "optimal" choice of operator overloads (optimal in terms of "performance", i.e. maximizing the binding to rvalue references)? Perhaps I'm asking for too much though and it's impossible... if so, then that's fine too. I just want to make sure I'm not missing anything.
Many thanks in advance
Addendum
First thanks to the quick responses I got, within minutes (!) - I really should have started posting here sooner...
It's becoming tedious replying in the comments, so I think a clarification of my intent with this class design is in order. Maybe you can point me to a fundamental conceptual flaw in my thought process if there is one.
You may notice that I don't hold any resources in the class like heap memory. Its members are only scalar types even. At first sight this makes it a suspect candidate for move-semantics based optimizations (see also this question that actually helped me a great deal grasping the concepts behind rvalue references).
However, since the classes this one is supposed to be a prototype for will be used in a performance-critical context (a 3D engine to be precise), I want to optimize every little thing possible. Low-complexity algorithms and maths-related techniques like look-up tables should of course make up the bulk of the optimizations as anything else would simply be addressing the symptoms and not eradicating the real reason for bad performance. I am well aware of that.
With that out of the way, my intent here is to optimize algebraic expressions with vectors and matrices that are essentially plain-old-data structs without pointers to data in them (mainly due to the performance drawbacks you get with data on the heap [having to dereference additional pointers, cache considerations etc.]).
I don't care about move-assignment or construction, I just don't want more temporaries being created during the evaluation of a complicated algebraic expression than absolutely necessary (usually just one or two, e.g. a matrix and a vector).
Those are my thoughts that might be erroneous. If they are, please correct me:
- To achieve this without relying on RVO, return-by-reference is necessary (again: keep in mind I don't have remote resources, only scalar data members).
- Returning by reference makes the function-call expression an lvalue, implying the returned object is not a temporary, which is bad, but returning by rvalue reference makes the function-call expression an xvalue (see 3.10.1), which is okay in the context of my approach (see 4)
- Returning by reference is dangerous, because of the possibly short lifetime of objects, but:
- temporaries are guaranteed to live until the end of the evaluation of the expression they were created in, therefore:
- making it safe to return by reference from those operators that take at least one rvalue-reference as their argument, if the object referenced by this rvalue reference argument is the one being returned by reference. Therefore:
- Any arbitrary expression that only employs binary operators can be evaluated by creating only one temporary when not more than one PoD-like type is involved, and the binary operations don't require a temporary by nature (like matrix multiplication)
(Another reason to return by rvalue-reference is because it behaves like returning by value in terms of rvalue-ness of the function-call expression; and it's required for the operator/function-call expression to be an rvalue in order to bind to subsequent calls to operators that take rvalue references. As stated in (2), calls to functions that return by reference are lvalues, and would therefore bind to operators with the signature T operator+(const T&, const T&)
, resulting in the creation of an unnecessary temporary)
I could achieve the desired performance by using a C-style approach of functions like add(Vector4 *result, Vector4 *v1, Vector4 *v2)
, but come on, we're living in the 21st century...
In summary, my goal is creating a vector class that achieves the same performance as the C-approach using overloaded operators. If that in itself is impossible, than I guess it can't be helped. But I'd appreciate if someone could explain to me why my approach is doomed to fail (the left-to-right operator evaluation issue that was the initial reason for my post aside, of course).
As a matter of fact, I've been using the "real" vector class this one is a simplification of for a while without any crashes or corrupted memory so far. And in fact, I never actually return local objects as references, so there shouldn't be any problems. I dare say what I'm doing is standard-compliant.
Any help on the original issue would of course be appreciated as well!
many thanks for all the patience again
c++ - C++11 - 右辺値ポインターの区別
変数をコンパイラで構築された文字列として区別するにはどうすればよいですか?
たとえば、右辺値"Hello, World"
の型はconst char*
. const char*
それ自体は、ポインターを変更できないという意味ではありません。ポインターを変更するchar* const
ことはできませんが、それはコンパイラーによって構築されるものではありません。
これは、 を保持するコンテナconst char*
の場合、C++ の移動セマンティクス以外の方法でデータをコピーする必要があるということですか? コンパイラで構築された文字列を移動し、他のすべての文字列をそのままにしておく方法はありますか?
たとえば、GCC 4.5.2 では、 ではint
なく型を返すメソッドは、 を返すint&
ものとして扱われint&&
ます。実際の標準がこのようになっているかどうかはわかりませんが、GCC が当分の間そうしていることです。
編集:明確にするために、ポインタが指す実際のメモリをコピーする必要があることを意味します。これは、新しいメモリを割り当てる必要があり、ポインターからのデータを新しい場所にコピーする必要があることを意味します。
c++ - 移動セマンティクスstd::move
std::move
機能がよくわかりません
なぜremove_reference
ですか?誰かが私に簡単な説明をしてもらえますか?
c++ - move セマンティクス std::move 使用方法
このコードがコンパイルされないのはなぜですか?
エラー C2440: 'return': 'int &&' の 'int' を変換できません