在 vs2012 中移动字符串
Move a string in vs2012
std::string t1("aaa");
const char *p = t1.c_str();
std::string t2(std::move(t1));
if (p == t2.c_str()) {
std::cout << "ok!" << std::endl;
}
此代码在 vs2012 中未打印任何内容。它只是在内部使用memmove
将字符串复制到t1
t2
。为什么?
正式地,正如jrok所指出的,你正在做的是未定义的行为,因此您无权投诉,无论如何实现的作用。 实际上,这将取决于实施。 标准不需要移动std::string
的构造函数对源字符串。 如果实现使用小字符串优化(例如,VC++ 也是如此(,字符串是小到有资格,那么它就无能为力但角色的记忆;char[]
他们在字符串对象本身。 CoW 实现(如 g++ 中的实现(可能会不做任何与它在副本中所做的不同的事情构造函数,理由是不值得打扰;你不会真正节省太多。 (但它可能,因为只是交换指针会节省一点。
我刚刚在 VC++ 中尝试了同样的事情,但字符串为 100字符。 它进行了交换(并且两个指针相等(。所以VC++的行为取决于字符串是否足够小,可以应用 SSO。 G++ 在所有情况下都交换。
Visualtudio 在真正移动指针之前比较字符串的长度,通过调试std::move
代码,它显示它复制长度小于 16 字节的字符串
void _Assign_rv(_Myt&& _Right)
{
// assign by moving _Right
if (_Right._Myres < this->_BUF_SIZE) //_BUF_SIZE is 16, comment mine
_Traits::move(this->_Bx._Buf, _Right._Bx._Buf,
_Right._Mysize + 1);
else
{ // copy pointer
this->_Getal().construct(&this->_Bx._Ptr, _Right._Bx._Ptr);
_Right._Bx._Ptr = pointer();
}
this->_Mysize = _Right._Mysize;
this->_Myres = _Right._Myres;
_Right._Tidy();
}
具体来说,这里发生的事情是"小字符串优化"。
Visual C++的 STL(以及许多其他(具有"胖"std::string
类,这些类可以在内部保存一个小字符串,而不需要任何内存分配。 这是对一些常见用例的优化。
即使有std::move
,因为你的字符串足够小,它完全存储在std::string
本身,所以必须复制。 如果您尝试使用较大的字符串,您的代码可能会起作用,尽管绝对不能保证它会起作用,并且您不应该依赖该行为。
本质上,将这些实现中的std::string
视为类似于:
class string {
// space for small strings; only used if _external is nullptr
char _local[16];
// pointer to heap-allocated memory; if nullptr, the string is stored in _local
char* _external;
// stores a string using small-string optimization is appropriate
void store(char* src) {
if (std::strlen(src) < sizeof(_local)) {
// small string, store in our local buffer and set _external to nullptr
std::strcpy(_local, src);
delete _external;
_external = nullptr;
} else if (src != _external) {
// large string, allocate space in heap
delete _external;
_external = new char[std::strlen(src) + 1];
std::strcpy(_external, src);
}
}
public:
// assign a C string to this string
string(char* src) : _external(nullptr) { store(src); }
string& operator=(char* src) { store(src); return *this; }
// be sure to properly use either _local or _external pointer
char* c_str() { return _external ? _external : _local; }
bool empty() const { return c_str()[0] == 0; }
};
- 通过字符串来计算长度需要更长的时间,而不是移动字符串几次?
- 尝试移动字符串中的每个位
- 为什么字符串流只读取整数中的第一个数字?如何使它只在空白处移动?
- 错误:移动文件时'QString'为非标量类型"std::__cxx11::字符串"
- 快速从文件中读取下一个字符串,而无需移动文件的位置
- 如何找到通过仅移动相邻字符创建的字符串的排列?-C++
- 通过单词列表将两个字符串移动以比较每个单词
- STD ::移动性能,同时将大字符串作为rvalue
- 如何在循环移动后从给定的字符串中找到一组不同的字符串
- 如何移动 std::ostringstream 的底层字符串对象?
- 从字符串和向量移动以不拥有任何堆内存
- 字符串将第一个单词移动到字符串的末尾
- 如何在不删除任何字符的情况下将字符从字符串中的某个位置移动到其最前面
- 需要从格式化字符串移动到二进制缓冲区
- C :在字符串#附录中移动语义
- 为什么包含std::字符串流的类的移动语义会导致编译器错误
- 是否建议将字符串std::移动到将被覆盖的容器中
- 试图编写能够从std::string中移动语义的字符串类
- 字符串移动构造函数是如何工作的
- 将字符串移动到矢量中