不適切な値の転送
転送されたオブジェクトが予期せず変更される場合がある
説明
この欠陥は、以下の場合に発生します。
std::moveを使用して、auto&&型またはT&&型のオブジェクトを含む、転送参照を関数に転送した場合。std::forwardを使用して、rvalue参照を関数に転送した場合。
以下のコードについて考えます。関数テンプレート callMethod では、パラメーター param1 が転送参照で、パラメーター param2 が rvalue 参照です。これらのパラメーターを関数 foo() に転送すると、コードで誤って転送参照 param1 に対して std::move が使用され、rvalue 参照 param2 に対して std::forward が使用されます。
#include<string>
#include<iostream>
template <class T> class bar{};
template<typename T>
void foo(std::string&& s, bar<T>&&){
//...
}
template <typename T>
void callMethod(T&& param1, bar<T>&& param2) {
foo(std::move(param1),std::forward<bar<T>&&>(param2));
}T&& または auto&& として宣言され、rvalue 参照は && として宣言されます。転送参照と rvalue 参照を混同すると、不適切な値の転送になります。 Polyspace® は、std::move または std::forward で参照が関数に転送されなかった場合に、この欠陥を報告しません。たとえば、次のコードは、rvalue 参照 b1 と転送参照 b2 を別の関数に転送しません。std::move を b2 とともに使用した場合、または std::forward を b1 とともに使用した場合、欠陥は発生しません。
template <typename T1, typename T2>
void func(T1& b1, T2&& b2)
{
const T1& b10 = std::forward<B>(b1);
const T2& b20 = std::forward<B>(b2);
const T1& b11 = std::move(b1);
const T2& b21 = std::move(b2);
}リスク
std::move と転送参照をともに使用すると、lvalue が予期せず変更される可能性があります。std::forward と rvalue 参照をともに使用すると、間違いが生じやすく、コードが複雑になる可能性があります。
修正方法
rvalue参照を関数に転送する場合は、std::moveを使用して、参照をrvalueにキャストします。転送参照またはユニバーサル参照を関数に転送する場合は、オブジェクトが
rvalueに制限される場合にのみ、std::forwardを使用して参照をrvalueにキャストします。
例
結果情報
| グループ: プログラミング |
| 言語: C++ |
| 既定値: 手書きコードはオン、生成コードはオフ |
コマンド ライン構文: INCORRECT_VALUE_FORWARDING |
| 影響度: High |
バージョン履歴
R2020b で導入