所以在我的VS2010上我可以编译代码如下:
boost::shared_ptr<boost::thread> internal_thread;
boost::packaged_task<void> internal_task_w(boost::bind(&thread_pool::internal_run, this, internal_thread));
internal_thread = boost::shared_ptr<boost::thread>( new boost::thread(std::move(internal_task_w)));
Run Code Online (Sandbox Code Playgroud)
使用boost 1.47.0和linux ...前两行是正常的但是在std :: move它给出了error: ‘move’ is not a member of ‘std’.在VS2010上它不需要任何特殊标头.所以我想知道它在Linux上需要哪个头,无论如何它都在STD中吗?如果不是如何通过提升或其他东西绕过它?
此代码按预期工作(在线处).最后v是空的,w因为它已经窃取了内容,所以不是空的v.
vector<int> v;
v.push_back(1);
cout << "v.size(): " << v.size() << endl;
auto vp = move(v);
vector<int> w(vp);
cout << "w.size(): " << w.size() << endl;
cout << "v.size(): " << v.size() << endl;
Run Code Online (Sandbox Code Playgroud)
但是,如果我取代auto vp=move(v)用
vector<int> && vp = move (v);
Run Code Online (Sandbox Code Playgroud)
然后它不动.相反,它复制,两个向量最后都是非空的.如图所示这里.
澄清:更具体地说,什么是自动衍生类型vp?如果不是vector<int> &&,那还有什么呢?为什么这两个例子虽然如此相似但却给出了不同的结果?
额外:我也试过这个,它仍然复制而不是移动
std :: remove_reference< vector<int> > :: type && vp = move(v);
Run Code Online (Sandbox Code Playgroud) 我无法理解右值引用的工作原理。我有以下代码:
void f(int&& i)
{}
int main()
{
int i = 42;
int&& r = std::move(i);
f(r);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在这里,我收到以下编译器错误:
prog.cpp: In function ‘int main()’:
prog.cpp:46:7: error: cannot bind rvalue reference of type ‘int&&’ to lvalue of type ‘int’
f(r);
^
prog.cpp:38:6: note: initializing argument 1 of ‘void f(int&&)’
void f(int&& i)
^
Run Code Online (Sandbox Code Playgroud)
当我显式声明r为右值引用时,为什么编译器认为我正在传递左值?这样做f(std::move(r))似乎有效,但我仍然不明白那里有什么不同。
这是因为在f(r)调用中r被视为左值吗?如果是,是什么类型的std::move(r)?
考虑这个代码片段
#include <iostream>
int foo() {
int a;
return a;
}
int main() {
auto &&ret = std::move(foo());
std::cout << ret;
}
Run Code Online (Sandbox Code Playgroud)
使用ASAN编译g++ -fsanitize=address -fno-omit-frame-pointer -g -std=c++17 main.cpp -o main,运行./main显示错误
==57382==ERROR: AddressSanitizer: stack-use-after-scope on address 0x00016b3cb480 at pc 0x000104a37e68 bp 0x00016b3cb450 sp 0x00016b3cb448
READ of size 4 at 0x00016b3cb480 thread T0
#0 0x104a37e64 in main main.cpp:8
#1 0x104a75084 in start+0x200 (dyld:arm64e+0x5084)
Run Code Online (Sandbox Code Playgroud)
但是如果我在 auto 之后删除引用,这段代码可以编译并运行,而不会出现 ASAN 给出的错误。我不明白的是,如果std::move返回对给定对象的引用,那么该对象(foo()在本例中是临时创建的)将在函数调用返回后被销毁std::move,因此无论它是绑定到右值引用还是分配给新值应该无效,因为该临时值在移动操作后已经被销毁,对吗?那么为什么 ASAN 在第二种情况下不会给出错误。
- - …
我试图理解移动语义的概念并做了一些测试。我有以下功能:
// testing the move semantic when passing
// argument to be modified without copying
void process_copy( std::vector<int>&& aVec)
{
std::cout << "Move semantic\n";
aVec.push_back(42);
}
Run Code Online (Sandbox Code Playgroud)
现在在主要功能中,以下内容:
int main()
{
std::vector<int> w_vec = {1,2,3,4,5};
process_copy( std::move(w_vec));
}
Run Code Online (Sandbox Code Playgroud)
我希望w_vec现在是空的,因为我通过移动转换(将左值转换为右值)传递了它。但结果现在w_vec包含6 个元素(42 个已添加到向量中)。
我想念的东西?是std::vector可移动的物体吗?
有人可以解释为什么B不编译,但C呢?我不明白为什么std :: move是必需的,因为变量已经是rvalue ref.
struct A {
int x;
A(int x=0) : x(x) {}
A(A&& a) : x(a.x) { a.x = 0; }
};
struct B : public A {
B() {}
B(B&& b) : A(b) {} // compile error with g++-4.7
};
struct C : public A {
C() {}
C(C&& c) : A(std::move(c)) {} // ok, but why?
};
Run Code Online (Sandbox Code Playgroud) 假设我有一个从自定义内存池分配的char*并填充了必要的数据.我在std :: string类的assign方法中使用了char*,并确保使用std :: move调用move varient.
void DoWork(char* my_pool_allocated_buffer) {
std::string s;
s.assign(std::move(my_pool_allocated_buffer));
//do some work with s
}
Run Code Online (Sandbox Code Playgroud)
我有两个问题.
在cpp 参考中的以下示例中:
#include <iostream>
#include <utility>
#include <vector>
#include <string>
int main()
{
std::string str = "Hello";
std::vector<std::string> v;
// uses the push_back(const T&) overload, which means
// we'll incur the cost of copying str
v.push_back(str);
std::cout << "After copy, str is \"" << str << "\"\n";
// uses the rvalue reference push_back(T&&) overload,
// which means no strings will be copied; instead, the
// Contents of str will be moved into the vector. This is
// less …Run Code Online (Sandbox Code Playgroud) std::exchange在cppreference.com上学习时,我遇到了下面粘贴的“可能的实现”。
template<class T, class U = T>
T exchange(T& obj, U&& new_value)
{
T old_value = std::move(obj);
obj = std::forward<U>(new_value);
return old_value;
}
Run Code Online (Sandbox Code Playgroud)
obj = std::forward在赋值语句中看到而不是看起来有点奇怪std::move,我认为这会产生相同的效果。
我的理解是,这std::move等效于static_cast右值引用类型(但更具表现力)并始终返回 xvalue,而std::forward返回传递的相同值类型。
我的问题是为什么std:forward在上面的代码片段中使用?是否有一个简单的经验法则来决定何时这是更好的选择?
当我在std::move没有任何分配的情况下使用时会发生什么?
std::string s = "Moving";
std::move(s); //What happens on this line to s?
//is s still valid here?
Run Code Online (Sandbox Code Playgroud) 我有巨大的结构 DataFrom 和 Data (实际上有不同的成员)。数据是从 DataFrom 创建的。
struct DataFrom{
int a = 1;
int b = 2;
};
static DataFrom dataFrom;
struct Data{
int a;
int b;
};
class DataHandler{
public:
static Data getData(const DataFrom& data2){
Data data;
setA(data, data2);
setB(data, data2);
return data;
}
private:
static void setA(Data& dest, const DataFrom& source){
dest.a = source.a;
}
static void setB(Data& dest, const DataFrom& source){
dest.b = source.b;
}
};
int main(){
auto data = DataHandler2::getData(dataFrom); // copy of whole Data …Run Code Online (Sandbox Code Playgroud) std::tuple我认为通过std::make_tuplerequire 右值引用参数( type )创建一个非常有意识的设计决策T&&。
然而,这意味着对象类型的移动语义 ( std::move 只不过是 to 的强制转换T&&),而且我对构建始终需要这样做的对象感到不太舒服std::tuple。
int x = 7, y = 5;
std::tuple<int, int> fraction = make_tuple<int, int>( x, y ); // fails
Run Code Online (Sandbox Code Playgroud)
关于上述内容,编译器说:
错误 C2664: 'std::tuple<int,int> std::make_tuple<int,int>(int &&,int &&)': 无法将参数 1 从 'int' 转换为 'int &&'
message : 您无法将左值绑定到右值引用
std::tuple如果您不使用,则可以从左值制作 a没有问题make_tuple:
std::tuple<int, int> fraction = { x, y }; // ok
Run Code Online (Sandbox Code Playgroud)
我的问题是,这是为什么?