在某个地方,我选择了“基本类型”(及其基本属性#[fundamental])一词,而现在我想了解更多有关它的信息。我隐约记得它是关于在某些情况下放宽一致性规则的。而且我认为引用类型就是这种基本类型。
不幸的是,在网上搜索并没有带给我很多。Rust参考没有提到它(据我所知)。我刚刚发现了一个有关创建元组基本类型和引入该属性的RFC 的问题。但是,RFC有一个关于基本类型的段落:
- 一种
#[fundamental]类型Foo是在其中实施全面实施Foo是一项重大变化。如上所述,&并且&mut是基本的。将此属性应用于Box,使其Box行为与相干性相同&并&mut相对于相干性。
我觉得这句话很难理解,感觉到我需要对整个RFC有深入的了解才能了解基本类型的这一点。我希望有人可以用更简单的术语来解释基本类型(当然,不必过多简化)。这个问题也可以作为一条容易找到的知识。
为了理解基本类型,我想回答以下问题(除了主要的“它们什至是什么?”问题,当然):
#[fundamental]吗?我试图在Rust中索引一个字符串,但编译器抛出一个错误.我的代码(Project Euler problem 4,playground):
fn is_palindrome(num: u64) -> bool {
let num_string = num.to_string();
let num_length = num_string.len();
for i in 0 .. num_length / 2 {
if num_string[i] != num_string[(num_length - 1) - i] {
return false;
}
}
true
}
Run Code Online (Sandbox Code Playgroud)
错误:
error[E0277]: the trait bound `std::string::String: std::ops::Index<usize>` is not satisfied
--> <anon>:7:12
|
7 | if num_string[i] != num_string[(num_length - 1) - i] {
| ^^^^^^^^^^^^^
|
= note: the type `std::string::String` cannot be indexed by …Run Code Online (Sandbox Code Playgroud) 我想将一个数组传递给一个函数并更改其中的内容.我怎么能这样做,这是我下面的代码,但当然它不起作用.
fn change_value(mut arr: &[i32]) {
arr[1] = 10;
}
fn main() {
let mut arr: [int; 4] = [1, 2, 3, 4];
change_value(&arr);
println!("this is {}", arr[1]);
}
Run Code Online (Sandbox Code Playgroud)
我收到错误:"无法分配给不可变的vec内容__CODE__".
我一直在寻找,但作为一个漂亮的新手Rust程序员,我找不到任何东西.另外,Rust对其语言进行了大量修改并没有帮助,因此很多方法都被弃用或删除了.
我在Rust写了一个线性代数库.
我有一个函数来获取给定行和列的矩阵单元格的引用.此函数以一对断言开始,行和列在边界内:
#[inline(always)]
pub fn get(&self, row: usize, col: usize) -> &T {
assert!(col < self.num_cols.as_nat());
assert!(row < self.num_rows.as_nat());
unsafe {
self.get_unchecked(row, col)
}
}
Run Code Online (Sandbox Code Playgroud)
在紧密的循环中,我认为跳过边界检查可能会更快,所以我提供了一个get_unchecked方法:
#[inline(always)]
pub unsafe fn get_unchecked(&self, row: usize, col: usize) -> &T {
self.data.get_unchecked(self.row_col_index(row, col))
}
Run Code Online (Sandbox Code Playgroud)
奇怪的是,当我使用这些方法来实现矩阵乘法(通过行和列迭代器)时,我的基准测试显示,当我检查边界时它实际上快了大约33%.为什么会这样?
我在两台不同的计算机上试过这个,一台运行Linux,另一台运行OSX,两者都显示效果.
完整的代码在github上.相关文件是lib.rs.感兴趣的功能是:
get 在第68行get_unchecked 在第81行next 在第551行mul 在第796行matrix_mul (基准)在第1038行请注意,我正在使用类型级数来参数化我的矩阵(通过虚拟标记类型也可以选择动态大小),因此基准测试将两个100x100矩阵相乘.
更新:
我已经大大简化了代码,删除了在基准测试中没有直接使用的东西并删除了泛型参数.我还编写了一个不使用迭代器的乘法实现,并且该版本不会产生相同的效果.有关此版本的代码,请参见此处.克隆minimal-performance分支并运行cargo bench将对两种不同的乘法实现进行基准测试(请注意,断言在该分支中以注释开头).
另外值得注意的是,如果我更改get*函数以返回数据的副本而不是引用(f64而不是&f64 …
以下指针别名示例:
pub unsafe fn f(a: *mut i32, b: *mut i32, x: *const i32) {
*a = *x;
*b = *x;
}
Run Code Online (Sandbox Code Playgroud)
编译成以下程序集(with -C opt-level=s):
example::f:
push rbp
mov rbp, rsp
mov eax, dword ptr [rdx]
mov dword ptr [rdi], eax
mov eax, dword ptr [rdx]
mov dword ptr [rsi], eax
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
请注意,x它被解除引用两次.LLVM没有将其视为noalias.我的第一个想法是避免在赋值中使用指针,而是使用安全引用(因为那些" 遵循LLVM的作用域noalias模型 ")来给优化器提示:
pub fn g(a: *mut i32, b: *mut i32, x: *const i32) {
let safe_a = unsafe { …Run Code Online (Sandbox Code Playgroud) 鉴于此代码:
struct RefWrapper<'a, T> {
r: &'a T,
}
Run Code Online (Sandbox Code Playgroud)
...编译器抱怨:
错误:参数类型
T可能活不够长考虑添加显式生命周期绑定,
T: 'a以便引用类型&'a T不会超过它指向的数据.
我已经多次看过这个错误了,到目前为止我只是听了编译器,一切都很顺利.但是,考虑更多,我不明白为什么我要写T: 'a.
据我了解,已经不可能得到这样的参考.有&'a T暗示有类型的对象T是至少生存'a.但是我们不能在所述对象中存储任何引用,这些引用指向具有比生命周期短的数据'a.这已经导致编译错误.
在这个意义上它已经是不可能得到一个&'a T地方T不活得长'a.因此,附加注释(T: 'a)不应该是必需的.
我对吗?我错了,如果是的话:如果T: 'a不需要,我怎么能破坏代码呢?
链接:
我最近一直在研究Rust编程语言.它是如何工作的?Rust代码似乎被编译成ELF或PE(等)二进制文件,但我无法找到有关如何完成的任何信息?它被编译成中间格式,然后用gxx编译其余部分吗?任何帮助(或链接)将非常感激.
执行rustc -C help节目(除其他外):
-C opt-level=val -- optimize with possible levels 0-3, s, or z
Run Code Online (Sandbox Code Playgroud)
我认为级别0到3非常直观:级别越高,执行的优化程度越高.但是,我不知道这些s和z选项正在做什么,我找不到与它相关的Rust相关信息.
我写了一个小程序添加到整数和使用"readelf -a executable_name"它显示了elf标题中的入口点地址:
Entry point address: 0x8048330
Run Code Online (Sandbox Code Playgroud)
我的可执行文件如何事先知道这个地址,甚至在加载器加载到内存之前?elf_format.pdf表示该成员提供系统首先转移控制的虚拟地址,从而启动该过程.任何人都可以解释这句话的含义是什么,这里虚拟地址的含义是什么?
另请告诉我,可执行文件的值为0x8048330,作为入口点地址.只是为了交叉检查我编译了另一个程序,为此,入口点地址保持相同的值0x8048330(两种情况下.text部分的偏移量为0x330).
我似乎无法做到这一点.我一直收到一个错误,说'len'在类型'&[str]'上不存在.
fn testLength(arr: &[String]) {
if arr.len >= 10 {
// Do stuff
}
}
Run Code Online (Sandbox Code Playgroud)
我还是Rust的新手,我知道这是一个指向原始字符串的指针.为什么我不能在运行时获取底层字符串的长度?谷歌搜索"生锈中的绳子长度"和"生锈中的阵列长度"这些东西绝对没有让我感到满意.
rust ×9
llvm-codegen ×4
arrays ×2
assembly ×1
c ×1
elf ×1
indexing ×1
lifetime ×1
linux ×1
optimization ×1
performance ×1
slice ×1
string ×1
x86 ×1