我正在使用外部库,有些代码让我停下来。基本上,有一个在循环内(在堆栈上)分配的 vector 。然后该 vector 通过引用传递给某个对象的构造函数,并用于初始化对象的 vector 字段之一,该字段未声明为引用。新创建的对象是否持有对不再存在的东西的引用?或者这只是一种更有效的 vector 复制方式,在这种情况下,它被分配到堆栈上的事实没有区别吗?
这是一个最小的例子:
class Holder {
public:
Holder(vector<int>& vref) : vec(vref) {}
vector<int> vec;
}
Holder* MakeHolder() {
vector<int> v {1, 2};
return new Holder(v);
}
int main() {
Holder *h = MakeHolder();
}
最佳答案
没有对已分离对象的引用,但我当然不会称其为“高效”。如果 ctor-initialiser 中没有 std::move
,则必须复制 vector 。
你可以把 std::move
放在那里,但是 Holder
使用起来会有点困惑。
我个人会按值获取 vector ,因此调用作用域可以 std::move
进入它(或传递一个将自动执行此操作的临时值),然后 std: :move
构造函数参数到新成员中。这样一来,您实际上一直只有一个 vector 。
class Holder {
public:
Holder(vector<int> vref) : vec(std::move(vref)) {}
vector<int> vec;
}
Holder* MakeHolder() {
vector<int> v {1, 2};
return new Holder(std::move(v)); // Or just `return new Holder({1,2});`
}
int main() {
Holder *h = MakeHolder();
}
并且,通过这种方式,如果您想保持原始 vector 处于事件状态(而不是移动),那也很好!只需将其传递进去,它就会被复制。事情将“正常工作”,而不需要真正知道构造函数代码中的内容(您只需要知道它需要一个值)。
我要更改的另一件事是引入 std::unique_ptr
,因为您当前有内存泄漏:
class Holder {
public:
Holder(vector<int> vref) : vec(std::move(vref)) {}
vector<int> vec;
}
std::unique_ptr<Holder> MakeHolder() {
return std::make_unique<Holder>({1,2});
}
int main() {
auto h = MakeHolder();
}
(有些人会拼写 MakeHolder()
的返回类型 auto
,但我不会。我认为了解您将要得到什么很重要。对于例如,否则你必须阅读代码才能知道结果的所有权语义是什么!它是原始指针吗?还有别的吗?)
关于c++ - 通过引用 C++ 中的构造函数传递堆栈分配的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51618428/