gpt4 book ai didi

c++ - RValue 引用、指针和复制构造函数

转载 作者:行者123 更新时间:2023-11-28 01:03:36 28 4
gpt4 key购买 nike

考虑以下代码:

int three() {
return 3;
}

template <typename T>
class Foo {
private:
T* ptr;

public:
void bar(T& t) { ptr = new T(t); }
void bar(const T& t) { ptr = new T(t); }
void bar(T&& t) { (*ptr) = t; } // <--- Unsafe!
};

int main() {
Foo<int> foo;

int a = 3;
const int b = 3;

foo.bar(a); // <--- Calls Foo::bar(T& t)
foo.bar(b); // <--- Calls Foo::bar(const T& t)
foo.bar(three()); // <--- Calls Foo::bar(T&& t); Runs fine, but only if either of the other two are called first!

return 0;
}

我的问题是,为什么第三个重载 Foo::bar(T&& t) 会导致程序崩溃?这里到底发生了什么?函数返回后参数t是否被销毁?

此外,我们假设模板参数 T 是一个非常大的对象,具有非常昂贵的复制构造函数。有没有什么方法可以使用 RValue References 将其分配给 Foo::ptr 而无需直接访问此指针并进行复制?

最佳答案

在这一行
void bar(T&& t) { (*ptr) = t; } // <--- Unsafe!
您可以取消引用未初始化的指针。这是未定义的行为。您必须首先调用 bar 的其他两个版本之一,因为您需要为您的对象创建内存。
所以我会做 ptr = new T(std::move(t)); .
如果你的类型 T 支持移动,移动构造函数将被调用。

更新

我会建议类似的东西。不确定您是否需要 foo 中的指针类型:

template <typename T>
class Foo {
private:
T obj;

public:
void bar(T& t) { obj = t; } // assignment
void bar(const T& t) { obj = t; } // assignment
void bar(T&& t) { obj = std::move(t); } // move assign
};

这将避免内存泄漏,这在您的方法中也很容易。
如果您真的需要类 foo 中的指针,那该怎么做:

template <typename T>
class Foo {
private:
T* ptr;

public:
Foo():ptr(nullptr){}
~Foo(){delete ptr;}
void bar(T& t) {
if(ptr)
(*ptr) = t;
else
ptr = new T(t);
}
void bar(const T& t) {
if(ptr)
(*ptr) = t;
else
ptr = new T(t);
}
void bar(T&& t) {
if(ptr)
(*ptr) = std::move(t);
else
ptr = new T(std::move(t));
}
};

关于c++ - RValue 引用、指针和复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7531783/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com