我做了一个两元素Vector
结构,我想重载+
运算符.
我使我的所有函数和方法都采用引用而不是值,我希望+
运算符以相同的方式工作.
impl Add for Vector {
fn add(&self, other: &Vector) -> Vector {
Vector {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
Run Code Online (Sandbox Code Playgroud)
根据我尝试的变化,我要么遇到生命问题,要么输入不匹配.具体来说,这个&self
论点似乎没有被视为正确的类型.
我已经看到了模板参数的例子上impl
,以及Add
,但他们只是导致不同的错误.
我发现如何为不同的RHS类型和返回值重载运算符?但即使我把一个use std::ops::Mul;
放在顶部,答案中的代码也不起作用.
我正在使用rustc 1.0.0-nightly(ed530d7a3 2015-01-16 22:41:16 +0000)
我不接受"你只有两个字段,为什么要使用参考"作为答案; 如果我想要一个100元素结构怎么办?我会接受一个答案,证明即使有一个大的结构我也应该通过值传递,如果是这样的话(我认为不是这样).我有兴趣知道结构大小的一个好的经验法则并且通过值vs struct传递,但这不是当前的问题.
我有一段奇怪的代码:
#![allow(unused)]
fn f<'a>() {}
fn g<'a: 'a>() {}
fn main() {
// let pf = f::<'static> as fn(); // (7)
let pg = g::<'static> as fn(); // (8)
//print!("{}", pf == pg);
}
Run Code Online (Sandbox Code Playgroud)
第7行如果没有注释就不能编译(有下面的错误),但是第8行可以编译。
#![allow(unused)]
fn f<'a>() {}
fn g<'a: 'a>() {}
fn main() {
// let pf = f::<'static> as fn(); // (7)
let pg = g::<'static> as fn(); // (8)
//print!("{}", pf == pg);
}
Run Code Online (Sandbox Code Playgroud)
'a: 'a
第4行是什么意思?
我正在制作一个简单的标记和紧凑的垃圾收集器.没有太多细节,它暴露的API是这样的:
/// Describes the internal structure of a managed object.
pub struct Tag { ... }
/// An unmanaged pointer to a managed object.
pub type Pointer = *mut usize;
/// Mapping from old to new locations.
pub type Adjust = BTreeMap<usize, Pointer>;
/// Mark this object and anything it points to as non-garbage.
pub unsafe fn survive(ptr: Pointer);
pub struct Heap { ... }
impl Heap {
pub fn new() -> Heap;
// Allocate an object with …
Run Code Online (Sandbox Code Playgroud) 以下代码工作正常,但为什么这是正确的代码?为什么foo()返回的临时的"c_str()"指针有效?我想,当输入bar()时,这个临时性已经被破坏了 - 但它似乎不是这样的.那么,现在我假设foo()返回的临时值将在调用bar()之后被销毁 - 这是正确的吗?为什么?
std::string foo() {
std::string out = something...;
return out;
}
void bar( const char* ccp ) {
// do something with the string..
}
bar( foo().c_str() );
Run Code Online (Sandbox Code Playgroud) 考虑这样的事情:
#include <iostream>
struct C {
C(double x=0, double y=0): x(x) , y(y) {
std::cout << "C ctor " << x << " " <<y << " " << "\n";
}
double x, y;
};
struct B {
B(double x=0, double y=0): x(x), y(y) {}
double x, y;
};
struct A {
B b[12];
A() {
b[2] = B(2.5, 14);
b[4] = B(56.32,11.99);
}
};
int main() {
const B& b = A().b[4];
C c(b.x, b.y);
}
Run Code Online (Sandbox Code Playgroud)
当我用-O0编译时,我得到了打印
C ctor …
Run Code Online (Sandbox Code Playgroud) 我正在尝试实现看起来像这个最小例子的东西:
trait Bar<T> {}
struct Foo<T> {
data: Vec<Box<Bar<T>>>,
}
impl<T> Foo<T> {
fn add<U: Bar<T>>(&mut self, x: U) {
self.data.push(Box::new(x));
}
}
Run Code Online (Sandbox Code Playgroud)
由于Rust默认为(据我所知)pass-by-ownership,我的心理模型认为这应该有效.该add
方法获取对象的所有权,x
并且能够将此对象移动到a中,Box
因为它知道完整类型U
(而不仅仅是特征Bar<T>
).一旦进入a Box
,框内项目的生命周期应该与框的实际生命周期相关联(例如,当pop()
从矢量中删除时,对象将被销毁).
然而,很明显,编译器不同意(我确信比我更了解...),要求我考虑添加一个'static
生命周期限定符(E0310).我99%肯定这不是我想要的,但我不确定我应该做什么.
为了澄清我的想法并帮助识别误解,我的心理模型来自C++背景,是:
Box<T>
本质上是 std::unique_ptr<T>
Copy
否则传递rvalue-reference&
大致const&
和&mut
大致&
我想编写一个程序,分两步编写一个文件.在程序运行之前,该文件可能不存在.文件名是固定的.
问题是OpenOptions.new().write()
可能会失败.在这种情况下,我想调用自定义函数trycreate()
.我们的想法是创建文件而不是打开它并返回一个句柄.由于文件名是固定的,trycreate()
没有参数,我不能设置返回值的生命周期.
我该如何解决这个问题?
use std::io::Write;
use std::fs::OpenOptions;
use std::path::Path;
fn trycreate() -> &OpenOptions {
let f = OpenOptions::new().write(true).open("foo.txt");
let mut f = match f {
Ok(file) => file,
Err(_) => panic!("ERR"),
};
f
}
fn main() {
{
let f = OpenOptions::new().write(true).open(b"foo.txt");
let mut f = match f {
Ok(file) => file,
Err(_) => trycreate("foo.txt"),
};
let buf = b"test1\n";
let _ret = f.write(buf).unwrap();
}
println!("50%");
{
let f = OpenOptions::new().append(true).open("foo.txt");
let mut f …
Run Code Online (Sandbox Code Playgroud) 我想知道为什么不需要释放静态数组?我知道在创建动态数组时,例如
int *p;
p = malloc(10*sizeof(int));
Run Code Online (Sandbox Code Playgroud)
我们必须使用以下内容释放分配的内存:
free(p);
Run Code Online (Sandbox Code Playgroud)
对于函数中的静态数组,静态数组将在被调用函数完成时自动释放.
我不明白的是:当使用如下函数返回静态数组时:
int *subFunc(){
static int a[5] = {1,2,3,4,5};
return a;
}
int main(){
int *p;
p = subFunc();
}
Run Code Online (Sandbox Code Playgroud)
如果在完成执行后自动释放静态数组,那么我们如何才能正确访问静态数组的值?
在Rust中,当我们想要一个包含引用的结构时,我们通常会定义它们的生命周期:
struct Foo<'a> {
x: &'a i32,
y: &'a i32,
}
Run Code Online (Sandbox Code Playgroud)
但是也可以为同一结构中的不同引用定义多个生命周期:
struct Foo<'a, 'b> {
x: &'a i32,
y: &'b i32,
}
Run Code Online (Sandbox Code Playgroud)
什么时候这样做有用?有人可以提供一些示例代码,这些代码在两个生命周期都'a
没有编译但是在生命周期时编译'a
并且'b
(反之亦然)?
浏览Rust文档的标记部分和维基百科有关子类型和方差的文章多次没有它提高我对生命周期子类型关系的理解,我感到愚蠢.
我想我只是习惯于"典型的OOP风格"子类型关系,比如"Cat <:Animal",意思是"Cat是动物的子类型",其中"S是T的子类型"意味着"任何术语S都可以安全在预期类型为T的术语中使用".到现在为止还挺好.
但这如何适用于生命周期?它现在在Rust中定义的方式显然是(*)
(#1)'a <:'b <=>生命周期a不超过生命周期b.
你可能会想"当然这意味着什么!" 可能是因为<:看起来类似于小于运算符或可能因为"sub"让你想到子集而且更短的寿命肯定是更长寿命的一个子集.但是' 如果'a'不再是'b',那么它' '真的是'b' 的子类型吗?让我们尝试应用维基百科对子类型关系的定义:
(#2)'a <:'b <=>生命周期a可以安全地用于预期寿命为b的上下文中.
我遇到的问题是我无法调和这个问题.你是如何从#2到#1的?因为对我来说,这似乎是一个矛盾...如果你期望某事至少是活着的b并且你有一个比b短的东西,你显然不能在那些有生命周期的东西中使用它是必需的,可以吗?它只是我还是我们得到了生命时间的子类型关系错误?
编辑:(*)根据#rust
IRC频道中的Ms2ger,情况就是如此.它也适用于Items
迭代器中使用的逆变寿命标记的文档.
Edit2:已删除ContravariantLifetime和CovariantLifetime标记.我们现在已经PhantomData
作为标记模块的替代品.