- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
以下示例来自 cpp reference :
#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 expensive, but also means str might now be empty.
v.push_back(std::move(str));
std::cout << "After move, str is \"" << str << "\"\n";
std::cout << "The contents of the vector are \"" << v[0]
<< "\", \"" << v[1] << "\"\n";
}
使用std::move
可能会导致原始值丢失。对我来说,它看起来像
v.push_back(std::move(str))
导致创建新成员 v[1]
。然后,
&v[1] = &str
但为什么它会破坏 str
中的值呢?这没有意义。
有很多关于 std::move
的复杂教程,比我自己的问题更难理解。
谁能写一下
v.push_back(std::move(str))
使用 c++03
的等价物?
我寻找一个解释,它的理解很容易,并且不包含诸如 x-value
、 static_cast
、remove_reference
等先决条件,因为他们自己需要首先理解 std::move
。请避免这种循环依赖。
这些链接也没有回答我的问题:7510182 , 3413470
因为我感兴趣的是 str
的危害,而不是 v[1]
会发生什么。
也欢迎使用像c++03
这样简单的伪代码。
更新:为了避免复杂化,让我们考虑一个更简单的 int
示例,如下所示
int x = 10;
int y = std::move(x);
std::cout << x;
最佳答案
根据实现,std::move
可以是内部内存地址的简单交换。
如果您在 http://cpp.sh/9f6ru 上运行以下代码
#include <iostream>
#include <string>
int main()
{
std::string str1 = "test";
std::string str2 = "test2";
std::cout << "str1.data() before move: "<< static_cast<const void*>(str1.data()) << std::endl;
std::cout << "str2.data() before move: "<< static_cast<const void*>(str2.data()) << std::endl;
str2 = std::move(str1);
std::cout << "=================================" << std::endl;
std::cout << "str1.data() after move: " << static_cast<const void*>(str1.data()) << std::endl;
std::cout << "str2.data() after move: " << static_cast<const void*>(str2.data()) << std::endl;
}
您将获得以下输出:
str1.data() before move: 0x363d0d8
str2.data() before move: 0x363d108
=================================
str1.data() after move: 0x363d108
str2.data() after move: 0x363d0d8
但结果可能因编译器和标准库的实现而异。
但实现细节可能更加复杂http://cpp.sh/6dx7j .如果您查看您的示例,那么您会发现为字符串创建拷贝并不一定需要为其内容分配新内存。这是因为几乎所有对 std::string
的操作都是只读的或需要分配内存。所以实现可以决定只做浅拷贝:
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string str = "Hello";
std::vector<std::string> v;
std::cout << "str.data() before move: "<< static_cast<const void*>(str.data()) << std::endl;
v.push_back(str);
std::cout << "============================" << std::endl;
std::cout << "str.data() after push_back: "<< static_cast<const void*>(str.data()) << std::endl;
std::cout << "v[0].data() after push_back: "<< static_cast<const void*>(v[0].data()) << std::endl;
v.push_back(std::move(str));
std::cout << "============================" << std::endl;
std::cout << "str.data() after move: "<< static_cast<const void*>(str.data()) << std::endl;
std::cout << "v[0].data() after move: "<< static_cast<const void*>(v[0].data()) << std::endl;
std::cout << "v[1].data() after move: "<< static_cast<const void*>(v[1].data()) << std::endl;
std::cout << "After move, str is \"" << str << "\"\n";
str = std::move(v[1]);
std::cout << "============================" << std::endl;
std::cout << "str.data() after move: "<< static_cast<const void*>(str.data()) << std::endl;
std::cout << "v[0].data() after move: "<< static_cast<const void*>(v[0].data()) << std::endl;
std::cout << "v[1].data() after move: "<< static_cast<const void*>(v[1].data()) << std::endl;
std::cout << "After move, str is \"" << str << "\"\n";
}
输出是
str.data() before move: 0x3ec3048
============================
str.data() after push_back: 0x3ec3048
v[0].data() after push_back: 0x3ec3048
============================
str.data() after move: 0x601df8
v[0].data() after move: 0x3ec3048
v[1].data() after move: 0x3ec3048
After move, str is ""
============================
str.data() after move: 0x3ec3048
v[0].data() after move: 0x3ec3048
v[1].data() after move: 0x601df8
After move, str is "Hello"
如果你看一下:
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string str = "Hello";
std::vector<std::string> v;
std::cout << "str.data() before move: "<< static_cast<const void*>(str.data()) << std::endl;
v.push_back(str);
std::cout << "============================" << std::endl;
str[0] = 't';
std::cout << "str.data() after push_back: "<< static_cast<const void*>(str.data()) << std::endl;
std::cout << "v[0].data() after push_back: "<< static_cast<const void*>(v[0].data()) << std::endl;
}
那么您会假设 str[0] = 't'
只会替换原位的数据。但不一定是这样http://cpp.sh/47nsy .
str.data() before move: 0x40b8258
============================
str.data() after push_back: 0x40b82a8
v[0].data() after push_back: 0x40b8258
move 基元,如:
void test(int i) {
int x=i;
int y=std::move(x);
std::cout<<x;
std::cout<<y;
}
大部分会被编译器完全优化掉:
mov ebx, edi
mov edi, offset std::cout
mov esi, ebx
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov edi, offset std::cout
mov esi, ebx
pop rbx
jmp std::basic_ostream<char, std::char_traits<char> >::operator<<(int) # TAILCALL
std::cout
使用相同的寄存器,x
和 y
被完全优化掉。
关于c++ - std::move 如何使原始变量的值无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51916526/
我正在开发一个小型图书馆,我需要做的一件事是让访问者访问一些数据并返回结果。 在一些较旧的 C++ 代码中,访问者需要声明一个 typedef return_type .例如,boost::stati
我正在尝试使用std:map类型的键和值制作std::any Visual Studio 2017 std::map m("lastname", "Ivanov"); std::cout (m["la
我已经在 C++ 的 map 中声明了一个集合为 std::map> .如何循环访问或打印设定值? 最佳答案 如果你知道如何迭代 std::map或 std::set单独地,您应该可以毫无问题地组合迭
如何循环? 我已经试过了: //----- code std::vector >::iterator it; for ( it = users.begin(); it != users.end();
我有两个用例。 A.我想同步访问两个线程的队列。 B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待另一个线程将内容存储到队列中。 对于用例 A,我看到了使用 std::lock_
我正在查看这两种类型特征的文档,但不确定有什么区别。我不是语言律师,但据我所知,它们都适用于“memcpy-able”类型。 它们可以互换使用吗? 最佳答案 不,这些术语不能互换使用。这两个术语都表示
我有以下测试代码,其中有一个参数 fS,它是 ofstream 的容器: #include #include #include #include int
这是这个问题的延续 c++ function ptr in unorderer_map, compile time error 我试图使用 std::function 而不是函数指针,并且只有当函数是
std::unordered_map str_bool_map = { {"a", true}, {"b", false}, {"c", true} }; 我们可以在此映射上使
我有以下对象 std::vector> vectorList; 然后我添加到这个使用 std::vector vec_tmp; vec_tmp.push_back(strDRG); vec_tmp.p
为什么 std::initializer_list不支持std::get<> , std::tuple_size和 std::tuple_element ?在constexpr中用得很多现在的表达式,
我有一个像这样定义的变量 auto drum = std::make_tuple ( std::make_tuple ( 0.3f , Ex
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
问题 我正在尝试将 lambda 闭包传递给 std::thread,它使用任意封闭参数调用任意封闭函数。 template std::thread timed_thread(Function&& f
我想创建一个模板类,可以容纳容器和容器的任意组合。例如,std::vector或 std::map ,例如。 我尝试了很多组合,但我必须承认模板的复杂性让我不知所措。我编译的关闭是这样的: templ
我有一个 std::vector>我将其分配给相同类型的第二个 vector 。 我收到这个编译器错误: /opt/gcc-8.2.0/include/c++/8.2.0/bits/stl_algob
有时候,我们有一个工厂可以生成一个 std::unique_ptr vector ,后来我们想在类/线程/你命名的之间共享这些指针。因此,最好改用 std::shared_ptr 。当然有一种方法可以
这个问题在这里已经有了答案: Sorting a vector of custom objects (14 个答案) 关闭 6 年前。 我创建了一个 vector vector ,我想根据我定义的参
我有三个类(class)成员: public: std::vector > getObjects(); std::vector > getObjects() const; privat
我是一名优秀的程序员,十分优秀!