我偶然发现了这个问题,在阅读了 ramslök 对已接受答案的评论后,我尝试了一个不是Copy.
令我惊讶的是它编译成功,但它的析构函数从未运行,有效地忘记了值,就好像std::mem::forget被调用一样。这是一个代码示例(Playground):
#[derive(PartialEq, Debug)]
struct A;
impl Drop for A {
fn drop(&mut self) {
println!("Dropping A");
}
}
fn main() {
let vec: Vec<A> = vec![];
let a = A;
assert_eq!(vec, [a; 0]);
}
Run Code Online (Sandbox Code Playgroud)
如果我们尝试在a之后使用assert_eq,它会抱怨该值已移动到数组中。
通过 已经可以忘记值std::mem::forget,并且它不会导致 UB,但仍然感觉很奇怪,如果没有编译器魔法是可能的。
我的问题是:这是一个错误,还是 Rust 的预期功能?
当我尝试运行以下代码时,clang(6.0)和g ++(8)与-std = c ++ 17都会给我一个static_assert错误:
#include <set>
struct A {};
struct ProcessComparator { inline bool operator()(const A&, const A&) { return true; } };
int main(void)
{
std::set<A, ProcessComparator> A_Set;
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
g ++ 8
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_tree.h:457:7:错误:由于需求'is_invocable_v',static_assert失败"比较对象必须作为const调用"
铿锵6.0
/usr/include/c++/8/bits/stl_tree.h:457:21:错误:静态断言失败:比较对象必须作为const调用
将const作为operator()签名的一部分来修复此问题:
#include <set>
struct A {};
/* Add const as part of the operator's signature */
struct ProcessComparator { inline bool operator()(const A&, const A&) const { return true; } };
int main(void)
{
std::set<A, ProcessComparator> A_Set;
return EXIT_SUCCESS;
} …Run Code Online (Sandbox Code Playgroud) 我有以下使用内联汇编的函数,目标mipsel-unknown-linux-gnu:
#![feature(asm)]
#[no_mangle]
pub unsafe extern "C" fn f(ptr: u32) {
let value: i8;
asm!(
"lb $v0, ($a0)",
in("$4") ptr,
out("$2") value,
);
asm!(
"sb $v0, ($a0)",
in("$4") ptr,
in("$2") value,
);
}
Run Code Online (Sandbox Code Playgroud)
我预计这会编译成以下内容:
lb $v0, ($a0)
sb $v0, ($a0)
jr $ra
nop
Run Code Online (Sandbox Code Playgroud)
注意:在此示例中,编译器可能会在跳转后将存储指令重新排序以使用延迟槽,但在我的实际用例中,我通过块返回asm,因此不必担心。鉴于此,我完全预料到了上面的装配。
相反,我得到的是:
00000000 <f>:
0: 80820000 lb v0,0(a0)
4: 304200ff andi v0,v0,0xff
8: a0820000 sb v0,0(a0)
c: 03e00008 jr ra
10: 00000000 nop
Run Code Online (Sandbox Code Playgroud)
编译器似乎不相信我的输出是 ani8并andi $v0, 0xff在那里插入了一条指令。
我需要准确地生成上面指定的程序集,因此我想删除该andi …
如果我们引用向量元素,然后调整向量的大小,则引用不再有效,迭代器也会发生同样的情况:
std::vector<int> vec{0, 1, 2, 3, 4, 5};
int& ref = vec[0];
auto itr = vec.begin();
cout << ref << " " << *itr << endl;
vec[0] = 7;
cout << ref << " " << *itr << endl;
vec.resize(100);
vec[0] = 3;
cout << ref << " " << *itr << endl;
Run Code Online (Sandbox Code Playgroud)
打印出:
0 0
7 7
0 0 // We expected a 3 here
Run Code Online (Sandbox Code Playgroud)
我知道只保留对向量本身的引用并调用 vec[0] 会更实用,但只是为了提问,是否可以保留一个始终为 vec[0] 的对象,即使物体被移动了?
我尝试编写一个小帮助器类来帮助解决此问题,但我不确定这是否是最好的方法,或者它是否会失败?
template<typename T>
struct HelperClass
{
std::vector<T>& vec;
size_t …Run Code Online (Sandbox Code Playgroud) 我正在构建一个BigInt类,当重载运算符时,| 和^,都将具有相似的函数语法,我想知道是否可以模拟运算符本身:
template<operator K>
BigInt operator K( const BigInt& a, const BigInt& b )
{
BigInt Result = 0;
uint64_t Max = max(a.GetSize() , b.GetSize()) /* max(a,b) is defined outside */
for (uint64_t n=0; n < Max; n++)
{
Result[n] = a[n] K b[N];
}
return Result;
}
Run Code Online (Sandbox Code Playgroud)
其中A [n]返回带有第n个数字(二进制)的bool,并将其应用于运算符&,| 和^,这样我就不会写出3个运算符重载,它们对于2个字母的例外都是相同的.
我知道这种语法不起作用,但我问是否有任何方法可以做你可能期望这种语法做的事情:用&替换K,| 或^,只有你在代码中写(a和b)时的那些.
如果它有帮助,这是我对类的定义:
class BigInt
{
private:
vector<bool> num;
public:
/* Constructors */
BigInt();
template<class T> BigInt(T);
/* Class Methods */
void RLZ(); /* Remove Leading Zeroes */
uint64_t …Run Code Online (Sandbox Code Playgroud)