新しい移動セマンティクスのテスト。
Move Constructor で発生していた問題について質問しました。しかし、コメントで判明したように、問題は実際には、標準の「コピーとスワップ」イディオムを使用すると、「Move Assignment」演算子と「Standard Assignment」演算子が衝突することです。
これは私が使用しているクラスです:
#include <string.h>
#include <utility>
class String
{
int len;
char* data;
public:
// Default constructor
// In Terms of C-String constructor
String()
: String("")
{}
// Normal constructor that takes a C-String
String(char const* cString)
: len(strlen(cString))
, data(new char[len+1]()) // Allocate and zero memory
{
memcpy(data, cString, len);
}
// Standard Rule of three
String(String const& cpy)
: len(cpy.len)
, data(new char[len+1]())
{
memcpy(data, cpy.data, len);
}
String& operator=(String rhs)
{
rhs.swap(*this);
return *this;
}
~String()
{
delete [] data;
}
// Standard Swap to facilitate rule of three
void swap(String& other) throw ()
{
std::swap(len, other.len);
std::swap(data, other.data);
}
// New Stuff
// Move Operators
String(String&& rhs) throw()
: len(0)
, data(null)
{
rhs.swap(*this);
}
String& operator=(String&& rhs) throw()
{
rhs.swap(*this);
return *this;
}
};
かなり標準的だと思います。
次に、次のようにコードをテストしました。
int main()
{
String a("Hi");
a = String("Test Move Assignment");
}
ここで、への割り当てa
は「Move Assignment」演算子を使用する必要があります。ただし、「標準割り当て」演算子 (標準のコピーとスワップとして記述されます) との衝突があります。
> g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/c++/4.2.1
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix
> g++ -std=c++11 String.cpp
String.cpp:64:9: error: use of overloaded operator '=' is ambiguous (with operand types 'String' and 'String')
a = String("Test Move Assignment");
~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
String.cpp:32:17: note: candidate function
String& operator=(String rhs)
^
String.cpp:54:17: note: candidate function
String& operator=(String&& rhs)
^
「Standard Assignment」演算子を次のように変更することで、これを修正できます。
String& operator=(String const& rhs)
{
String copy(rhs);
copy.swap(*this);
return *this;
}
しかし、これは、コピーとスワップを最適化するコンパイラの機能を台無しにするため、良くありません。コピーアンドスワップイディオムとは何ですか? を参照してください。こことここ
それほど明白ではない何かが欠けていますか?