我有一个std::unique_ptr和另一个原始指针.我希望原始指针指向unique_ptr没有任何所有权的内容.它是只读关系:
auto bar=std::make_unique<foo>();
auto ptr=bar.get();// This may point to another value later
Run Code Online (Sandbox Code Playgroud)
这不好吗?还有其他选择吗?
注意:真实的例子比较复杂.他们不在同一个班级.
我得到的印象是,Rust旨在用于高度安全的系统.然后我注意到原始指针允许任意指针算术,它们可能导致内存安全和安全问题.
无论是在ffi教程中还是在自动生成的接口中,*const T大部分时间都使用指针。据我所知,&T和之间的区别*const T只是*const T不必满足某些条件,例如不为空,并且取消引用是不安全的。
fn main() {
unsafe {
do_something(&TestStruct {data: 3})
}
}
#[repr(C)]
pub struct TestStruct {
data: u32
}
extern "C" {
fn do_something(arg: &TestStruct);
}
Run Code Online (Sandbox Code Playgroud)
这段代码可以编译并运行。因为外部函数的用法与内部函数类似,所以我不明白为什么在那里使用原始指针作为默认值。
我在我与包裹在一个数据工作的情况Arc,我有时最终使用into_raw,以获得原始指针的基础数据。我的用例还需要类型擦除,因此原始指针通常被强制转换为 a *const c_void,然后在重新构造Arc.
我遇到过这样一种情况,即能够在Arc不需要知道底层数据的具体类型的情况下克隆它会很有用。据我了解,只要我从未真正取消引用数据,Arc仅出于调用目的而使用虚拟类型重建 应该是安全clone的。因此,例如,这应该是安全的:
pub unsafe fn clone_raw(handle: *const c_void) -> *const c_void {
let original = Arc::from_raw(handle);
let copy = original.clone();
mem::forget(original);
Arc::into_raw(copy)
}
Run Code Online (Sandbox Code Playgroud)
有什么我遗漏的东西会使这实际上不安全吗?另外,我认为答案也适用于Rc,但如果有任何差异,请告诉我!
我有一个必须以原始指针形式检索的结构。
pub struct BufferData {
/// Memory map for pixel data
pub map: Arc<Box<memmap::MmapMut>>,
pub otherdata: i32,
}
Run Code Online (Sandbox Code Playgroud)
我需要写入它的map字段,所以我将原始指针解引用到结构中,然后尝试写入它的数据字段。但是,我收到以下错误。
pub struct BufferData {
/// Memory map for pixel data
pub map: Arc<Box<memmap::MmapMut>>,
pub otherdata: i32,
}
Run Code Online (Sandbox Code Playgroud)
如何使map字段可变和可写?
使用以下代码可重现该错误:
extern crate memmap;
use std::fs::File;
use std::sync::Arc;
use std::boxed::Box;
use std::ops::Deref;
pub struct BufferData {
/// Memory map for pixel data
pub map: Arc<Box<memmap::MmapMut>>,
pub otherdata: i32,
}
fn main() -> () {
// Somewhere on other module …Run Code Online (Sandbox Code Playgroud) 在以下代码的情况下:
#include<iostream>
class Sample
{
public:
Sample* getSelf()
{
return this;
}
};
int main()
{
Sample s;
if(reinterpret_cast<void*>(&s) == reinterpret_cast<void*>(s.getSelf()))
std::cout << "Same address" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
if 语句中的条件是否保证为真?
我进行了转换void*以确保比较原始地址,以防在比较特定指针类型时出现一些怪癖。
#include <vector>
enum ListOfGameStates
{
// List of game states
};
class GameState()
{
public:
GameStates(); // Initializes protected (global) variables
virtual ListOfGameStates run() = 0;
protected:
// Heavyweigh resource managers containing all resources and other global vars
}
class GameStateManager()
{
public:
GameStateManager(); // Creates all game states
~GameStateManager(); // Deletes all game states
void run(); // Switches from one state to another state
private:
// A vector of raw pointers to game states. GameState is a base class. …Run Code Online (Sandbox Code Playgroud) 当您将 a 用于unique_ptr<T>前向声明的类型时T,unique_ptr析构函数要求 theT是完整的,但还需要移动赋值运算符(和reset),根据此表:
因此,对于您的pImpl习惯用法,要正确实现它,您必须声明 thedelete和 the move assignment method(这作为副作用,将它们标记为非内联):
class impl_t;
class A
{
std::unique_ptr<impl_t> p_impl;
public:
// Implement in A.cpp as A::~A() = default;
~A();
// Implemented in A.cpp as A& operator=(A&&) = default;
A& operator=(A&& he);
};
Run Code Online (Sandbox Code Playgroud)
但是,由于std::unique_ptr是动态内存的 RAII 解决方案,并且您pImpl已经在一个类中,并且无论如何您都被迫编写析构函数,因此管理原始指针不是更好吗,因为您的类已经是 RAII-就像从 ? 的角度来看p_impl:
class impl_t;
class A
{
impl_t* p_impl;
public:
~A(); // The destructor …Run Code Online (Sandbox Code Playgroud) raw-pointer ×10
c++ ×5
rust ×5
pointers ×2
raii ×2
unique-ptr ×2
unsafe ×2
c++11 ×1
dereference ×1
ffi ×1
immutability ×1
type-erasure ×1
weak-ptr ×1