下面的代码为什么编译?
#include <vector>
#include <iostream>
struct Foo {
std::vector<int> bar = {1, 2, 3};
};
int main()
{
Foo foo1;
const Foo& foo2 = foo1;
std::vector<int> target;
std::move(foo2.bar.begin(), foo2.bar.end(), std::back_inserter(target));
return 0;
}
std::move的文档说
执行此操作后,“移动自”范围中的元素仍将包含适当类型的有效值,但不一定与移动前的值相同。
所以这实际上可以改变对象foo2,即使它声明为const。为什么这样做有效?
用例子来说明Andrey Semashev的答案,考虑一下:
#include <vector>
struct movable
{
movable() = default;
movable(const movable&) = delete;
movable& operator=(const movable&) = delete;
movable(movable&&) = default;
movable& operator=(movable&&) = default;
};
struct copyable
{
copyable() = default;
copyable(const copyable&) = default;
copyable& operator=(const copyable&) = default;
copyable(copyable&&) = delete;
copyable& operator=(copyable&&) = delete;
};
int main()
{
// original example
const std::vector<int> si;
std::vector<int> ti;
std::move(si.begin(), si.end(), std::back_inserter(ti)); // OK
// example 2
const std::vector<copyable> sc;
std::vector<copyable> tc;
std::move(sc.begin(), sc.end(), std::back_inserter(tc)); // OK
// example 3
const std::vector<movable> sv;
std::vector<movable> tv;
std::move(sv.begin(), sv.end(), std::back_inserter(tv)); // ERROR - tries to use copy ctor
return 0;
}
即使copyable
没有移动构造函数,示例2编译时没有错误,因为std::move
在这里选择了复制构造函数。
另一方面,示例3无法编译,因为可移动的
的移动构造函数被否定(更好的词?)通过sv
的一致性。你得到的错误是:
error: use of deleted function 'movable::movable(const movable&)'
这里有一个完整的例子。
所以这实际上可以改变对象foo2,即使它声明为const。为什么这样做有效?
如果可以的话,std::move
算法可以移动输入元素。
对于每个输入元素,它执行*dest=std::move(*from)
,其中dest
和from
是输出和输入迭代器。由于from
取消对常量对象的引用,std::move(*from)
创建一个右值引用const int
如果元素属于具有用户定义的复制和移动构造函数的类类型
T
,则重载解析必须选择复制构造函数(T(const T
底线是
std::move
(带迭代器的算法)正在执行移动操作,该操作可能调用移动构造函数或赋值,也可能不调用移动构造函数或赋值。如果调用了move构造函数或赋值,并且该移动对源具有破坏性,那么算法将修改源元素。在其他情况下,它将只执行一个复制。
问题内容: 我知道ES6尚未标准化,但是目前许多浏览器都支持 JS中的关键字。 规范中写道: 常量的值不能通过重新分配而更改,并且常量也不能重新声明。因此,尽管可以在不初始化的情况下声明常量,但这样做是没有用的。 当我做这样的事情: 我看到一切正常仍和是。 但是,如果这样做,我的常量数组已更改。现在是这样,顺便说一句,我仍然无法用更改它。 我这是一个错误,还是我错过了什么?我在最新的chrome和
这应该很容易,但我一直在撞我的头。 我有数字向量 我有一个数值向量v2。v2始终是v1的子集。 我想从v1中删除v2中的所有元素,但每个v2元素只删除一个(而且完全是一个)v1元素。 所需输出 如果我希望将保留在v1之外。使用很容易。 如果我希望将与v1保持一致。此外,也能起到作用。 如果我希望将与v1保持一致。现在返回。不是我想要的。 当答案输入时,我很可能会用头撞我的键盘,但现在我还没有得到最
问题内容: 考虑一下Java中的以下接口: 和以下类: 为什么类A可以出现并覆盖接口I的最终常量? 自己尝试: 问题答案: 尽管事实上您正在隐藏变量,但是知道可以在java中更改final字段非常有趣,因为您可以在此处阅读: Java 5-“最终”不再是最终的 挪威Machina Networks的Narve Saetre昨天给我发了一封便条,其中提到我们可以将句柄更改为最终数组,这是很遗憾的。我
问题内容: 大家好!我有一个简单的问题。…为什么我可以从main方法中获得一个私有变量?我知道,我在包含类中,但这是主要的。我相信主体不是包含它的类的一部分……那么我不会去找私人成员,但是我可以……为什么?请帮助… thx 问题答案: Main是您的类的一部分,您已经在类中声明了它:) main不是您的对象的一部分,它不会是您从该类创建的对象的任何部分,但它仍然是该类的一部分。这对于任何静态函数都
我试图创建一个图,它将有V个顶点。我正在使用向量的向量来表示图(作为邻接列表)。我的图中的节点是从0到V-1的编号,所以adj向量的索引代表了节点的数量。除非我搞错了,adj[u]代表一个向量,所以我应该可以使用adj[u].push_back(v)将顶点v推入顶点u的邻接列表中。所以在我的例子中,adj[4]应该得到与节点4相邻的顶点所在的向量,而.push_back(1) 这不会发生的。我想这
问题内容: 我创建了以下课程 然后我从类中实例化了一个常量值 问题: 为什么我可以更改变量的内容?这不是常数吗?有人可以帮我解释一下,非常感谢。 问题答案: 正如@Wain所说的–这是由于引用类型的性质造成的。实例是一个常量仅意味着您不能为其分配新的引用–但却没有提及实例本身的实际可变性。 如果将类更改为结构,则将看到行为随 _值_类型的不同,因为更改属性会更改您的实际值-因此,如果它是常量,则无