move使用原始指针时如何使用赋值运算符。
除了这样做之外还有其他方法吗:
void Function(T* dest)
{
T* src = LoadT();
(*dest) = std::move(*src);
delete src;
}
Run Code Online (Sandbox Code Playgroud) 该功能是将文件内容提取到向量中,如下所示:
std::vector<uint8_t> GetFileContents(const std::string& filename)
{
std::ifstream file(filename, std::ios::binary);
if (!file.good())
{
return {};
}
file.seekg(0, std::ios::end);
std::streampos fileSize = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<uint8_t> fileData(fileSize);
file.read((char*) &fileData[0], fileSize);
return fileData;
}
Run Code Online (Sandbox Code Playgroud)
就行:
std::vector<uint8_t> fileData(fileSize);
file.read((char*) &fileData[0], fileSize);
return fileData;
Run Code Online (Sandbox Code Playgroud)
fileData 向量被复制到一个临时向量中以在此处返回?
我需要更改为:
std::vector<uint8_t> fileData(fileSize);
file.read((char*) &fileData[0], fileSize);
return std::move(fileData);
Run Code Online (Sandbox Code Playgroud)
进行移动并保存矢量复制操作?
支持移动的功能还需要进行其他更改吗?
对于空的情况, std::move({}) 有任何价值吗?
我很好奇,使用std::move将左值整数转换为右值与0向该整数添加 a 之间有什么实际区别吗?或任何其他中性算术运算(乘以1、减去0等)。
添加0:
int f(int&& i){
i++;
return i;
}
int main(){
int x = 43;
f(x+0);
}
Run Code Online (Sandbox Code Playgroud)
使用std::move:
#include <iostream>
int f(int&& i){
i++;
return i;
}
int main(){
int x = 43;
f(std::move(x));
}
Run Code Online (Sandbox Code Playgroud)
我知道我们不能对所有类型执行这种中立的操作,但我的问题特别是关于整数而不是其他类型。
如果我有一个迭代器指向 STL 容器中的一个元素,并且我用迭代器移动了该元素,那么标准是否保证迭代器仍然有效?我可以将它与容器的方法一起使用吗container::erase?
容器是连续容器(例如 )vector还是非连续容器(例如 )也很重要吗list?
std::list<std::string> l{"a", "b", "c"};
auto iter = l.begin();
auto s = std::move(*iter);
l.erase(iter); // <----- is it valid to erase it, whose underlying element has been removed?
Run Code Online (Sandbox Code Playgroud) 我正在开发一个遗留应用程序,其类的名称Point3D如下所示......
template <class T>
class Point3D final
{
T values[3];
public:
Point3D();
Point3D(T x, T y, T z);
explicit Point3D(const T value);
Point3D(const Point3D& point);
explicit Point3D(const Point2D<T>& point);
~Point3D();
};
Run Code Online (Sandbox Code Playgroud)
这个类在很多地方都被用作vector<Point3D<double>>. 向量的大小为 > 10^5。此外,遗留代码将此向量作为值传递并按值返回。这使得应用程序非常慢。同样在很多地方,我们都有类似的代码,如下所示......
for(auto i: n){ // This loop runs for 10^4 times
Point3D<double> vpos;
vpos[X_COORDINATE] = /*Some calculation*/;
vpos[Y_COORDINATE] = /*Some calculation*/;
vpos[Z_COORDINATE] = /*Some calculation*/;
Positions.push_back(vpos);
}
Run Code Online (Sandbox Code Playgroud)
为了提高性能,我计划修改Point3D要使用的类,move semantics如下所示......
template <class T>
class Point3D final {
T* …Run Code Online (Sandbox Code Playgroud) 我正在尝试学习C++的新功能,即移动构造函数和赋值X::operator=(X&&),我发现了一些有趣的例子, 但我唯一不理解但更不同意的是移动ctor和赋值运算符中的一行(在下面的代码中标记):
MemoryBlock(MemoryBlock&& other)
: _data(NULL)
, _length(0)
{
std::cout << "In MemoryBlock(MemoryBlock&&). length = "
<< other._length << ". Moving resource." << std::endl;
// Copy the data pointer and its length from the
// source object.
_data = other._data;
_length = other._length;
// Release the data pointer from the source object so that
// the destructor does not free the memory multiple times.
other._data = NULL;
other._length = 0;//WHY WOULD I EVEN BOTHER TO SET IT …Run Code Online (Sandbox Code Playgroud) 我在Visual Studio 2015 v4中尝试此代码.
using namespace std;
void * operator new(size_t size) {
cout << "Creating new " << endl;
void * p = malloc(size);
return p;
}
class CTest {
private:
string a;
string b;
public:
CTest( const string &&one , const string && two ) :a(move(one)), b(move(two)) {}
};
int main() {
CTest("one", "one" );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此代码在Visual Studio中输出"Creating new"4次,这意味着它分配内存4次.但是遵循语义它应该只分配两次(在数据段中创建2个文字,创建一个和两个函数参数= 2个alloc,然后将它们的资源移动到a和b成员变量)
在g ++下编译它会两次输出"Creating new",就像它应该的那样.
我需要设置任何设置才能使VS遵循移动语义吗?据我所知,它应默认支持.
感谢帮助.
#include <range/v3/all.hpp>
#include <vector>
#include <string>
#include <deque>
using namespace std::literals;
int main()
{
auto src = std::vector{"123"s, "456"s, "789"s};
auto movable_rng = ranges::subrange(
std::make_move_iterator(src.begin()),
std::make_move_iterator(src.end()));
auto dst = ranges::to<std::deque<std::string>>(movable_rng);
for (auto e : src)
{
std::cout << e << std::endl;
}
for (auto e : dst)
{
std::cout << e << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
用 libc++ 用 clang 10 编译,输出为:
123
456
789
123
456
789
Run Code Online (Sandbox Code Playgroud)
正如我所料,结果应该是:
""
""
""
123
456
789
Run Code Online (Sandbox Code Playgroud)
为什么即使是迭代器,ranges-v3 也不移动元素 std::move_iterator?
========更新======
我的范围版本是: …
我看了这个约(令人难以置信的好写的)文章转发参考用C斯科特迈尔斯++ 11.
现在,重点关注本文的这一部分:
Run Code Online (Sandbox Code Playgroud)template <class... Args> void emplace_back(Args&&... args); // deduced parameter types ? type deduction; ... // && ? universal references
因此,与其他情况相比,省略号不会&&成为右值引用,但它仍然是通用引用.
根据我的理解,当我们有通用引用时,我们可以调用函数传递rvalue和lvalues(哇,太酷了!)
现在,我已经实现了这个功能:
template <typename ReturnType, typename... Args>
ReturnType callFunction(MemFunc<ReturnType, Args...> memFunc, Args&& ... args) { ...
Run Code Online (Sandbox Code Playgroud)
因此(使用与前一示例相同的逻辑)&&意味着转发引用.
但如果我试着打电话:
typedef vector<double> vecD;
vecD vec;
mem.callFunction<vecD, vecD>(sortFunc, vec);
Run Code Online (Sandbox Code Playgroud)
编译器会抱怨 You cannot bind an lvalue to an rvalue reference
为什么会这样?
整个代码:
#include <functional>
#include <vector>
using namespace std;
struct MultiMemoizator { …Run Code Online (Sandbox Code Playgroud) Foo(Foo&& other) {
this->bar = other.bar;
other.bar = nullptr;
}
Foo(Foo* other) {
this->bar = other->bar;
other->bar = nullptr;
}
Run Code Online (Sandbox Code Playgroud)
上面两个似乎只是在做同样的事情。那么为什么推荐使用移动构造函数呢?它提供了哪些优势?