移动const对象是否有有用的方案
Is there a useful scenario for moving const objects?
我意识到"您不能移动const对象" 的共同知识并非完全正确。您可以,如果将MOVE CTOR声明为
X(const X&&);
下面的完整示例:
#include <iostream>
struct X
{
X() = default;
X(const X&&) {std::cout << "const moven";}
};
int main()
{
const X x{};
X y{std::move(x)};
}
生活在coliru
问题:有什么理由为什么想要这样的东西?有用/实用的情况吗?
您的示例不会移动任何东西。是的,您编写了std::move
来获取rvalue,然后调用了一个移动构造函数,但实际上没有什么最终被移动了。而且不能,因为对象是 const
。
除非您感兴趣的成员被标记为mutable
,否则您将无法执行任何"移动"。因此,没有有用的场景甚至可能的情况。
不确定它是否实用,但是可以合法地法律规定,只要修改后的数据成员是mutable
。
这个程序是合法的,如果您喜欢这种事情,很容易就很难遵循:
#include <iostream>
#include <string>
struct animal
{
animal(const animal&& other) : type(other.type) {
other.type = "dog";
}
animal() = default;
mutable std::string type = "cat";
};
std::ostream& operator<<(std::ostream& os, const animal& a)
{
return os << "I am a " << a.type;
}
std::ostream& operator<<(std::ostream& os, const animal&& a)
{
return os << "I am a " << a.type << " and I feel moved";
}
int main()
{
const auto cat = animal();
std::cout << cat << std::endl;
auto dog = std::move(cat);
std::cout << cat << std::endl;
std::cout << dog << std::endl;
std::cout << std::move(dog) << std::endl;
}
预期输出:
I am a cat
I am a dog
I am a cat
I am a cat and I feel moved
正如评论所指出的那样,您实际上不能将任何内容从参数对象中移出,因为它是const(至少,不是没有const cons,这是一个坏主意它可能导致UB(。因此,对于移动而言,这显然没有用。移动语义的全部目的是提供性能优化,这不是在这里发生的,所以为什么要进行呢?
也就是说,我只能想到两个有用的情况。第一个涉及"贪婪"的构造函数:
#include <iostream>
struct Foo {
Foo() = default;
Foo(const Foo&) { std::cerr << "copy constructor"; }
Foo(Foo&&) { std::cerr << "copy constructor"; }
template <class T>
Foo(T&&) { std::cerr << "forward"; }
};
const Foo bar() { return Foo{}; }
int main() {
Foo f2(bar());
return 0;
}
此程序打印"向前"。原因是因为模板中的推论类型将是const Foo
,使其成为更好的匹配。当您具有完美的转发变异构造函数时,这也会显示出来。代理对象常见。当然,按const值返回是不好的做法,但是严格来说,这不是不正确的,这可能会破坏您的班级。因此,您应该真正提供Foo(const Foo&&)
过载(仅委派给复制构造函数(;将其视为在编写高质量通用代码时越过t或点缀i。
当您要明确删除移动构造函数或移动转换操作员时,第二种情况发生:
struct Baz {
Baz() = default;
Baz(const Baz&) = default;
Baz(Baz&&) = delete;
};
const Baz zwug() { return {}; }
int main() {
Baz b2(zwug());
}
此程序编译,因此作者失败了他们的任务。原因是因为const ref Overloads与const rvalues匹配,并且未明确删除const rvalue构造。如果要删除移动
第二个例子似乎很晦涩,但说您正在写一个提供字符串视图的课程。您可能不想允许暂时从字符串构造它,因为您面临损坏的更大风险。
- 运行同一解决方案的另一个项目的项目
- Project Euler问题4的错误解决方案
- 计算每个节点的树高,帮助我解释这个代码解决方案
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- visual c++,如何获取解决方案目录中的代码
- 有没有办法在远程设备上打开和编辑visual Studio 2017解决方案
- C++Matching Brackets 2解决方案不起作用
- 在 ubuntu3 上C++ goto 定义有什么解决方案吗16.04?
- 其中降频广播实际上是有用的
- C++11 中不同类型的对象的 std::array 的替代方案
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- 我的固定时间步长与增量时间和插值的解决方案是错误的吗?
- 无法在问题解决方案中执行输出逻辑
- 最大的回文产品 - 程序未运行,编写解决方案但无法理解问题
- 从预序遍历构造 bst 的 c++ 和 python 解决方案之间的区别
- 在一个解决方案中针对第三方静态库 (Creo) 的不同版本(版本)进行构建
- 如何巧妙地编写两个函数——一个用于检查是否存在解决方案,另一个用于获取所有解决方案
- 移动const对象是否有有用的方案