RVO を使用すると、コピーのコストを発生させることなく、関数からローカル変数を返すことができます。これは、変数のサブオブジェクトを返すときにも機能しますか?
他の回答から、戻り値用に予約されたスペースに収まらないため、完全なオブジェクトのサイズが返されるオブジェクトよりも大きい場合はそうではありません。しかし、完全なオブジェクトが「空」である場合、つまりサイズがサブオブジェクトと同じ場合はどうでしょうか?
この質問をする私の根拠:
単純なオブジェクトがあるとします
struct Data {
std::string s;
int i;
};
そして、データのよりインテリジェントなビューとして機能するラッパー クラス:
class WrapperRef {
Data& d;
public:
WrapperRef(Data& data) : d(data) {}
// some dummy functions operating on the data
char& foo() { return d.s[d.i]; }
};
これは、実装を容易にするために戻る一部の関数によって内部的に使用されData
ますが、インターフェイスはこれを反映しません (つまり、関数はラッパー自体を返しません)。だから私は関数を持っているかもしれません:
Data makeTheData(...) {
Data localData;
WrapperRef wrapper{localData};
// Manipulate the data using the wrapper
// ...
return localData;
}
このユース ケースは私のラッパーでは一般的であるため、これをカプセル化するクラスに置き換えたいと考えています。つまり、 の最初の 2 行を、サブオブジェクトとラッパーの機能をmakeTheData
含む単一のローカル オブジェクトに置き換えます。Data
class ContainingWrapper {
Data d;
public:
ContainingWrapper() = default;
// some dummy functions
char& foo() { return d.s[d.i]; }
// Convert to actual Data object. Maybe use other means instead such as a getter method?
operator Data&() { return d; }
};
Data makeTheData(...) {
ContainingWrapper wrapper;
// Manipulate the data using the wrapper
// ...
return wrapper;
}
これは、ラッパーの一般的な使用例を実装するのに役立ちます。オブジェクトはContainingWrapper
オブジェクトと同じサイズであるData
ため、RVO は技術的に可能であるはずです。
RVO のパフォーマンス (これは非常に重要です) を失うことなく、この機能を (メンバーまたは基本サブオブジェクトを使用して、あるいは別の手段で) 実現できますか? as ifルールが適用され、RVO が可能になるように、オプティマイザが の 2 番目の実装を最初makeTheData
の実装に変更できるようになりますか?