当您将 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) 根据文档,ManuallyDrop<T>是一个零成本的包装.这是否意味着我可以取消引用从原始指针转换ManuallyDrop<T>到的原始指针T?
您的经验中更常见的是:func1()或funct2()?假设func1和func2最好不要作为Foo类方法.
void func1(unique_ptr<Bar>& bar) { /* alter pointed to object's attributes */ }
void func2(Bar* const bar) { /* alter pointed to object's attributes */ }
class Foo
{
unique_ptr<Bar> bar;
void mutate_bar1(){ func1(bar); }
void mutate_bar2(){ func2(bar.get()); }
}
Run Code Online (Sandbox Code Playgroud) 如果我这样做,
int* p = new int(10);
std::shared_ptr<int>(p);
delete p;
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?shared_ptr删除原始指针后是无效的吗?在这种情况下,有没有办法确保内存访问安全?
如果我有struct,例如:
#[derive(Clone, Copy)]
#[repr(C, packed)]
pub struct SomeData {
a: u16,
b: u64,
c: u32,
d: u16,
}
Run Code Online (Sandbox Code Playgroud)
如何将其复制到内存中的特定位置,例如0x1000有效地复制到内存中的某个位置?会这样的吗?
let dst_addr: u64 = 0x1000;
let src = SomeData {a: 1, b: 2, c: 3, d: 4};
unsafe {
let tmp: &[u8; 10] = transmute(src);
copy(dst_addr as *mut _, tmp);
}
Run Code Online (Sandbox Code Playgroud)
请注意,repr(C, packed)这里实际需要这部分.
该软件在裸x86_64,ring 0上运行,没有操作系统或其他限制.另外,我在没有标准库的情况下进行编程,因此只有core库才能实现这一点.
这当然是不安全的,但这不是问题.
编辑:只是澄清:我正在复制到未初始化的内存.
我目前正在学习C++,来自C#/ Java背景,使用visual studio 2017.
我有一个关于在堆上创建对象并在路上正确引用它们的问题.到目前为止,我遇到了多个教程和做事方式.有些人建议尽可能使用智能指针,其他人则发誓使用魔鬼工具.
我目前的主要看起来像这样:
//Main
Person *makePerson()
{
string name;
int age;
cout << "Input name: ";
cin >> name;
cout << "Input age: ";
cin >> age;
return new Person(name, age);
}
Child *makeChild(Person &parent)
{
return new Child(*makePerson(), &parent);;
}
int main()
{
cout << "---Input parent data---" << endl;
Person *person = makePerson();
cout << "printing: " << *person << endl;
cout << "---Input child data---" << endl;
Child *child = makeChild(*person);
cout …Run Code Online (Sandbox Code Playgroud) 我目前正在做一个项目,更准确地说是一个七巧板游戏。我有段错误问题,我不明白为什么。
鉴于我有一个完整的项目,我将尝试简化问题:我有一个 GameManager 类,其中特别包含一个 Menu 对象(和其他东西,但我认为这并不重要。gameManager 用于初始化这个对象并管理它。菜单包含一个按钮向量(每个按钮都有一个 lambda 来在用户单击它时执行操作)。
std::vector<std::unique_ptr<Button>> buttons;
Run Code Online (Sandbox Code Playgroud)
为了说明它是如何工作的,我将举一个例子:如果用户点击“加载”按钮,游戏管理器将删除菜单中包含的当前按钮并在该菜单中添加新按钮。
void GameManager::initMainMenuButtons() {
...
menu -> addButton(std::unique_ptr<Button>(new Button(x1, y1, x2, y2, "Create",
[this]{
std::cout << "Create level" << std::endl;
menu->clear()
initCreateLevelButtons();
actionManager->setMenu(menu);
}
)));
...
}
Run Code Online (Sandbox Code Playgroud)
在该代码示例中,我有一个方法 initMainMenuButtons 可以在菜单中添加几个按钮,例如“加载”或“退出”。当用户单击“创建”时,我想更改界面(添加和删除按钮)。所以,要删除按钮,我调用方法 clear()
void Menu::clear() {
buttons.clear();
decorationPieces.clear(); // not interesting
}
Run Code Online (Sandbox Code Playgroud)
我正在使用 unique_ptr,因此,我不必手动删除按钮。到目前为止,没问题:按钮的向量似乎是空的(大小为 0)。接下来,调用方法 initCreateLevelButtons()。此方法与 initMainMenu 非常相似:它在菜单中添加按钮,仅此而已。在此调用期间,按钮似乎正确添加到矢量中,我在最后打印了矢量的内容,矢量包含正确的按钮。
在那里,问题出现了:在调用 initCreateLevelButtons() 之后,当我想使用菜单时会出现段错误,因此actionManager->setMenu(menu);不起作用。我尝试打印 menu std::cout << menu << std::endl,并测试此指针是否为 nullptr,但它也不起作用。我不明白为什么菜单在 initCreateLevelButtons() 的最后一行似乎是正确的,然后就无效了。如果我不清除按钮的矢量(菜单->清除指令),程序可以工作,但是,最后一个按钮仍然在这里)。
我尝试使用原始指针,我注意到只要按钮没有被删除,程序就能够清除向量(如果我添加一个循环来删除按钮,就会出现问题),所以,我得出的结论是问题是按钮删除。我不明白为什么,我被卡住了。我不知道我解释得好不好,因为,正如我已经说过的,代码是整个项目的一部分,很难在不引入其他东西的情况下引入类。如果您需要详细信息或方法的完整代码,我可以提供。
我正在使用一个函数(它是库的一部分),它返回一个uint8_t*指向已在堆上分配并保存图像像素数据的内存的原始指针。这个函数的调用者负责调用free指针。
我调用此函数的代码有许多提前终止的分支,因此我需要free(buffer)在许多点调用。我认为最好将缓冲区包装在 a 中,unique_ptr以便当它超出范围时,内存会自动释放。
我怎样才能做到这一点?
作为参考,函数 decleration 看起来像这样:(uint8_t* getFrame()我已经知道图像的宽度、高度和 num 通道以及缓冲区的长度);
fn main() {
println!("{:p}", std::mem::size_of::<*const u32>());
}
Run Code Online (Sandbox Code Playgroud)
当我在操场上尝试这个时,它失败了:
fn main() {
println!("{:p}", std::mem::size_of::<*const u32>());
}
Run Code Online (Sandbox Code Playgroud)
有没有办法像这样打印原始指针的大小*const u32?
struct MyCell<T> {
value: T
}
impl<T> MyCell<T> {
fn new(value: T) -> Self {
MyCell { value }
}
fn get(&self) -> &T {
&self.value
}
fn set(&self, new_value: T) {
unsafe {
*(&self.value as *const T as *mut T) = new_value;
}
}
}
fn set_to_local(cell: &MyCell<&i32>) {
let local = 100;
cell.set(&local);
}
fn main() {
let cell = MyCell::new(&10);
set_to_local(&cell);
}
Run Code Online (Sandbox Code Playgroud)
当调用时cell.set(&local),假设cellis'x和'&localis ,我被告知协方差规则将更改from到 的'y类型。cell&MyCell<'x, …
raw-pointer ×10
c++ ×6
rust ×4
unique-ptr ×3
unsafe ×3
pointers ×2
shared-ptr ×2
c++11 ×1
function ×1
heap ×1
heap-memory ×1
lifetime ×1
low-level ×1
memmove ×1
raii ×1
vector ×1