我在Rust中创建了一个数据结构,我想为它创建迭代器.不可变的迭代器很容易.我目前有这个,它工作正常:
// This is a mock of the "real" EdgeIndexes class as
// the one in my real program is somewhat complex, but
// of identical type
struct EdgeIndexes;
impl Iterator for EdgeIndexes {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
Some(0)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
pub struct CGraph<E> {
nodes: usize,
edges: Vec<E>,
}
pub struct Edges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a CGraph<E>,
}
impl<'a, E> Iterator …
Run Code Online (Sandbox Code Playgroud) 我有这个特点和简单的结构:
use std::path::{Path, PathBuf};
trait Foo {
type Item: AsRef<Path>;
type Iter: Iterator<Item = Self::Item>;
fn get(&self) -> Self::Iter;
}
struct Bar {
v: Vec<PathBuf>,
}
Run Code Online (Sandbox Code Playgroud)
我想实现以下Foo
特征Bar
:
impl Foo for Bar {
type Item = PathBuf;
type Iter = std::slice::Iter<PathBuf>;
fn get(&self) -> Self::Iter {
self.v.iter()
}
}
Run Code Online (Sandbox Code Playgroud)
但是我收到了这个错误:
error[E0106]: missing lifetime specifier
--> src/main.rs:16:17
|
16 | type Iter = std::slice::Iter<PathBuf>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected lifetime parameter
Run Code Online (Sandbox Code Playgroud)
我发现无法在相关类型中指定生命周期.特别是我想表达迭代器不能超过self
生命周期.
我如何修改Foo
特征或Bar
特征实现来使其工作?
考虑以下代码:
const char* someFun() {
// ... some stuff
return "Some text!!"
}
int main()
{
{ // Block: A
const char* retStr = someFun();
// use retStr
}
}
Run Code Online (Sandbox Code Playgroud)
在函数中someFun()
,"Some text!!"
存储的位置(我认为它可能在ROM的某个静态区域)以及它是什么范围 一生?
指向的内存是否会在retStr
整个程序中被占用,或者在块A退出后被释放?
GCC的实现破坏了std::initializer_list
返回full-expression结束时从函数返回的数组.它是否正确?
此程序中的两个测试用例都显示在使用值之前执行的析构函数:
#include <initializer_list>
#include <iostream>
struct noisydt {
~noisydt() { std::cout << "destroyed\n"; }
};
void receive( std::initializer_list< noisydt > il ) {
std::cout << "received\n";
}
std::initializer_list< noisydt > send() {
return { {}, {}, {} };
}
int main() {
receive( send() );
std::initializer_list< noisydt > && il = send();
receive( il );
}
Run Code Online (Sandbox Code Playgroud)
我认为该计划应该有效.但潜在的标准有点令人费解.
return语句初始化一个返回值对象,就像它被声明一样
std::initializer_list< noisydt > ret = { {},{},{} };
Run Code Online (Sandbox Code Playgroud)
这initializer_list
将从给定的初始化器系列初始化一个临时及其底层数组存储,然后initializer_list
从第一个初始化器初始化另一个.阵列的寿命是多少?"数组的生命周期与initializer_list
对象的生命周期相同." 但其中有两个; 哪一个是模棱两可的.8.5.4/6中的示例(如果它按照公布的方式工作)应该解决数组具有复制到对象的生命周期的歧义.然后返回值的数组也应该存在于调用函数中,并且应该可以通过将它绑定到命名引用来保留它.
我想写这个结构:
struct A {
b: B,
c: C,
}
struct B {
c: &C,
}
struct C;
Run Code Online (Sandbox Code Playgroud)
本B.c
应借A.c
.
A ->
b: B ->
c: &C -- borrow from --+
|
c: C <------------------+
Run Code Online (Sandbox Code Playgroud)
这是我尝试过的:struct C;
struct B<'b> {
c: &'b C,
}
struct A<'a> {
b: B<'a>,
c: C,
}
impl<'a> A<'a> {
fn new<'b>() -> A<'b> {
let c = C;
A {
c: c,
b: B { c: &c },
}
}
}
fn …
Run Code Online (Sandbox Code Playgroud) 如何在PHP中设置会话生存期?只要请求存在,我想将其设置为永久.请求是AJAX.我处理AJAX请求的PHP代码是:
// AJAX.php
<?php
session_start();
$_SESSION['counter'] = $_SESSION['counter'] + 1;
header('Content-type: application/json');
echo json_encode(array('tick' => $_SESSION['counter']));
?>
Run Code Online (Sandbox Code Playgroud)
和JavaScript:
$(document).ready(function() {
function check() {
getJSON('ajax.php');
}
function getJSON(url) {
return $.getJSON(
url,
function(data) {
$("#ticker").html(data.tick);
}
);
}
setInterval(function() {
check();
}, 10000); // Tick every 10 seconds
});
Run Code Online (Sandbox Code Playgroud)
会话总是在300秒后重置.
我无法表达Iterator
实现的返回值的生命周期.如何在不更改迭代器的返回值的情况下编译此代码?我希望它返回一个引用的向量.
很明显,我没有正确使用生命周期参数,但在尝试了我放弃的各种方法之后,我不知道如何处理它.
use std::iter::Iterator;
struct PermutationIterator<T> {
vs: Vec<Vec<T>>,
is: Vec<usize>,
}
impl<T> PermutationIterator<T> {
fn new() -> PermutationIterator<T> {
PermutationIterator {
vs: vec![],
is: vec![],
}
}
fn add(&mut self, v: Vec<T>) {
self.vs.push(v);
self.is.push(0);
}
}
impl<T> Iterator for PermutationIterator<T> {
type Item = Vec<&'a T>;
fn next(&mut self) -> Option<Vec<&T>> {
'outer: loop {
for i in 0..self.vs.len() {
if self.is[i] >= self.vs[i].len() {
if i == 0 {
return None; // we are done …
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
不需要,我怎么能破坏代码呢?
链接:
在我偶然发现下面的代码之前,我确信类型的生命周期参数中的生命周期总是比其自己的实例更长.换句话说,给定一个foo: Foo<'a>
,那么'a
总是会活得更久foo
.然后我被@Luc Danton(游乐场)介绍给这个反辩论代码:
#[derive(Debug)]
struct Foo<'a>(std::marker::PhantomData<fn(&'a ())>);
fn hint<'a, Arg>(_: &'a Arg) -> Foo<'a> {
Foo(std::marker::PhantomData)
}
fn check<'a>(_: &Foo<'a>, _: &'a ()) {}
fn main() {
let outlived = ();
let foo;
{
let shortlived = ();
foo = hint(&shortlived);
// error: `shortlived` does not live long enough
//check(&foo, &shortlived);
}
check(&foo, &outlived);
}
Run Code Online (Sandbox Code Playgroud)
尽管foo
创建者hint
似乎认为生命周期与其自身一样长,并且对它的引用被传递给更广泛范围内的函数,但代码完全按原样编译.取消注释代码中声明的行会触发编译错误.或者,更改Foo
为struct tuple (PhantomData<&'a ()>)
也会使代码不再使用相同类型的错误进行编译(Playground).
如何有效的Rust代码?这里编译器的原因是什么?
C++20 标准草案的[basic.scope.pdecl]/1在注释中包含以下(非规范性)示例(合并拉取请求 3580之前的部分引用,请参阅此问题的答案):
unsigned char x = x;
Run Code Online (Sandbox Code Playgroud)
[...] x 用它自己的(不确定的)值初始化。
这实际上在 C++20 中有明确定义的行为吗?
通常T x = x;
,由于x
的值在初始化完成之前是不确定的,因此表单的自初始化具有未定义的行为。评估不确定的值通常会导致未定义的行为([basic.indent]/2),但在[basic.indent]/2.3中有一个特定的例外,它允许直接unsigned char
从unsigned char
具有不确定值的左值初始化变量(导致使用不确定值初始化)。
这本身并不会因此导致不确定的行为,但会为其他类型T
不属于无符号窄字符类型或std::byte
如int x = x;
。这些注意事项也适用于 C++17 及之前的版本,另请参阅底部的链接问题。
然而,即使对于unsigned char x = x;
,当前草案的[basic.lifetime]/7说:
类似地,在对象的生命周期开始之前 [...] 使用不依赖于其值的泛左值的属性是明确定义的。在以下情况下,程序具有未定义的行为:
泛左值用于访问对象,或
[...]
这似乎意味着x
示例中的that值只能在其生命周期内使用。
[...]
类型 T 的对象的生命周期在以下情况下开始:
- [...] 和
- 它的初始化(如果有)完成(包括空初始化)([dcl.init]),
[...]
因此x
的生命周期仅在初始化完成后才开始。但是在引用的例子中 …