我希望在将对象传递给另一个更改其状态的对象后以只读方式访问该对象.我知道访问一个对象时,通过借用仍然可以控制它是一个问题.
extern crate renderay_rs;
use renderay_rs::*;
fn draw_canvas(canvas: &Canvas) {
let max_height = canvas.height;
let max_width = canvas.width;
for iterator_y in 0..max_height {
for iterator_x in 0..max_width {
print!("{}", canvas.array[iterator_y * iterator_x]);
}
print!("\n");
}
}
fn main() {
let point = Point { x: 5, y: 5 };
let mut canvas = Canvas {
width: 10,
height: 10,
array: vec!['o'; 10*10],
};
let mut renderer = CanvasRenderer::new(&mut canvas);
renderer.render_point('A', point);
draw_canvas(canvas);
}
Run Code Online (Sandbox Code Playgroud)
我觉得我应该在renderer.render_point(..., ...)方法之后结束借款.有办法吗?该对象无需借用它或CanvasRenderer在其状态发生变化之后借用.
我之前使用过块范围,但我对这种方法感到不满意.我希望你能给我一个更好的选择!
#include <iostream>
class A {
public:
A() { std::cout << "Constructor" << std::endl; }
A(const A& a) { std::cout << "Copy Constructor" << std::endl; }
A& operator=(const A& a) { std::cout << "Copy = operator" << std::endl; }
A(A&& a) { std::cout << "Move Constructor" << std::endl; }
A& operator=(A&& a) { std::cout << "Move = operator" << std::endl; }
~A() { std::cout << "Destructor" << std::endl; }
};
void f(A&& a) { std::cout << "function" << std::endl; }
int …Run Code Online (Sandbox Code Playgroud) 我这样说明了一下:
fn main() {
let mut opt1 = Some(1);
// compiler complains that opt2 doesn't have to be mutable
let mut opt2 = Some(1);
fn take_inner(mut opt: Option<u8>) {
opt.take();
};
opt1.take();
take_inner(opt2);
println!("opt1 {:?}", opt1); // prints "opt1 None"
println!("opt2 {:?}", opt2); // prints "opt2 Some(1)"
}
Run Code Online (Sandbox Code Playgroud)
为什么opt.take()函数内的调用与外部调用(相对于main函数的作用域)有不同的效果?
以下代码
using vptr = std::vector<std::unique_ptr<int>>;
auto m = std::unordered_map<int, std::any>{};
m.try_emplace(0, move(vptr{}));
Run Code Online (Sandbox Code Playgroud)
无法编译,抱怨使用的已删除副本构造函数unique_ptr。在模板参数中替换std::any为之后,vptr此代码将编译,因此问题显然与any
如何强制std::any移动而不是复制?
我得到了一个简单的 CTab 类,它包含诸如一维数组的指针、数组的大小和以下复制构造函数之类的字段:
CTab::CTab(const CTab &cOther)
{
pi_tab = new int[cOther.i_size];
i_size = cOther.i_size;
for (int ii = 0; ii < cOther.i_size; ii++)
pi_tab[ii] = cOther.pi_tab[ii];
std::cout << "Copy ";
}
Run Code Online (Sandbox Code Playgroud)
关于move语义需求,我还写了move construcor:
CTab::CTab(CTab && cOther)
{
pi_tab = cOther.pi_tab;
i_size = cOther.i_size;
cOther.pi_tab = NULL;
cOther.i_size = 0;
std::cout << "MOVE ";
}
Run Code Online (Sandbox Code Playgroud)
以前,我被要求重载“+”运算符,以便它返回 2 个数组的串联。现在,我正在努力修改使用移动语义以减少制作副本的数量。我不知道以前代码的哪一部分会产生不必要的副本,如果是这样,如何更改代码以使其满足给定任务的条件。有任何想法吗?
不使用移动语义的重载运算符:
CTab CTab::operator+(const CTab cOther)
{
CTab newTab;
newTab.bSetSize(i_size + cOther.i_size);
for (int i = 0; i < i_size; i++)
newTab.pi_tab[i] = pi_tab[i]; …Run Code Online (Sandbox Code Playgroud) 这个 C++ 代码:
void f(int& i) {
cout << "by reference" << endl;
}
void f(const int& i) {
cout << "by const reference" << endl;
}
void f(int&& i) {
cout << "by rvalue reference" << endl;
}
int main() {
int x;
const int y = 5;
cout << "f(x): ";
f(x);
cout << "f(y): ";
f(y);
cout << "f(x+y): ";
f(x+y);
cout << "f(move(x)): ";
f(move(x));
cout << "f(move(y)): ";
f(move(y));
cout << "f(move(x+y)): ";
f(move(x+y));
} …Run Code Online (Sandbox Code Playgroud) 这是一个典型的向量删除-擦除操作的样子:
auto toErase = std::remove_if(vec.begin(), vec.end(),
[val](obj_t const& obj) { return obj.myval == val; }
); // This actually moves objects around !
vec.erase(toErase, vec.end());
Run Code Online (Sandbox Code Playgroud)
这在大多数情况下都可以正常工作,但我遇到了obj_t类型不允许移动或复制语义的情况。对象是用 插入的vec.emplace_back(),我正在寻找一种remove_if不需要复制或移动的替代方法。
它是否已经存在于某处?如果没有,它将如何建造?
有这个简单的类:
#include <iostream>
class B
{
public:
//default constructor
B(const char* str = "\0") {
std::cout << "Constructor called\n";
}
//copy constructor
B(const B& b) {
std::cout << "Copy constructor called\n";
}
//move constructor
B(B&& b) {
std::cout << "Move constructor called\n";
}
};
Run Code Online (Sandbox Code Playgroud)
这些语句之间在移动语义方面有什么区别:
B o1 = B("abc");
B o2 = B(B("abc"));
Run Code Online (Sandbox Code Playgroud)
这两行等价吗?
我已经使用了相当数量的 C++,但没有那么多std::list.. 在我当前的项目中,我需要一个std::list<..>数据成员,以及跟踪列表中带有std::list<..>::iterator. 该对象也必须是可移动的,但在我的情况下,默认的移动构造函数是不可能的。这里std::list做了一些让我感到惊讶的事情。
考虑
#include <list>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
template<typename T>
void test() {
T l { 1, 2, 3, 4, 5 };
cout << "l = "; for(const auto& e: l) cout << e << " "; cout << endl;
auto pos = find(l.begin(), l.end(), 6);
if (pos == l.end()) cout << "l end\n";
cout << "---- moving l > lmv ----" << endl; …Run Code Online (Sandbox Code Playgroud) MCVE:http : //coliru.stacked-crooked.com/a/ef442eca9b74c8f1
我想按照在 lambda 中移动捕获中的教程来移动lambda 函数中的参数。
#include <string>
#include <iostream>
#include <functional>
class B{};
void f(B&& b){}
int main(){
B b;
auto func_lambda=[b{std::move(b)}](){
//f(std::move(b)); // also fails
f(b); // also fails
};
//: std::function<void()> func_cache=func_lambda();
// will be stored and called after 'b' is out of scope
}
Run Code Online (Sandbox Code Playgroud)
我收到此错误:-
main.cpp: 在 lambda 函数中: main.cpp:10:11: 错误: 无法将类型 'B&&' 的右值引用绑定到类型 'const B' 的左值 main.cpp:5:12: 注意:初始化参数 1 of ' void f(B&&)'
我也尝试过[b=std::move(b)]但失败了(链接=通过移动捕获的 lambda 函数传递给函数 …
move-semantics ×10
c++ ×8
c++17 ×2
copy-elision ×2
rust ×2
algorithm ×1
c++11 ×1
constructor ×1
iterator ×1
lambda ×1
list ×1
move ×1
mutability ×1
stdany ×1
vector ×1