为什么我不能重新分配以前在 C++ 堆栈上分配的变量('Frame' 的复制赋值运算符被隐式删除)?
Why can't I reassign a variable that was formerly allocated on the stack in C++ (copy assignment operator of 'Frame' is implicitly deleted)?
我有以下设置:
struct Frame {
Frame(vector<Region> regions_)
: regions(regions_){}
const vector<Region> regions;
};
现在,在我的代码的不同部分,我想创建一个 vector<Frame>
并创建以下 for
循环:
vector<Frame> shot;
Frame currentFrame = generateRandomFrame();
for (int i = 0; i < length; i++) {
shot.push_back(currentFrame);
currentFrame = generateNextFrame(currentFrame); // this line gives the error
}
其中 generateNextFrame
具有以下签名:
Frame FrameGenerator::generateNextFrame(Frame previousFrame)
现在,这段代码无法编译并出现以下错误:
copy assignment operator of 'Frame' is implicitly
deleted because field 'regions' has no copy assignment
operator const vector<Region> regions;
现在,我不完全理解这个错误信息。我强烈认为这与 currentFrame
分配在 堆栈 而不是 堆 上有关,因此我可以'只是重新分配变量。然而,作为 C++ 的新手,我不熟悉如何处理这些情况。我应该在这里改用指针并尝试在堆上分配 currentFrame
吗?
明确地说,我的目标是生成一系列 frames
(这取决于之前的一些帧)。谁能给我指出正确的方向?
更新:
非常感谢评论中的所有提示,我现在明白问题出在我将 regions
声明为 const
。我重写了代码以使用指针而不是堆变量,现在看起来像这样:
vector<Frame> shot;
Frame currentFrame = generateRandomFrame();
Frame *currentFramePtr = ¤tFrame; // the first frame in the shot is random
for (int i = 0; i < length; i++) {
shot.push_back(*currentFramePtr);
Frame tmpFrame = generateNextFrame(*currentFramePtr);
currentFramePtr = &tmpFrame;
}
这段代码现在可以编译,但是它仍然没有达到我想要的效果。根据我的理解,它现在应该可以工作了,因为我将 currentFrame
存储在一个指针中,所以我可以很容易地用我创建的新对象覆盖它。但似乎仍然存在一个错误,帧生成没有按预期工作(即生成的任何新帧都带有 0 个区域,而区域数量应与前一帧相同)。任何人都可以看到我的代码的这个更新版本有什么问题吗?
您的 struct
声明了一个 const
成员,由于 const
成员没有复制赋值运算符,这会强制编译器隐式删除默认的复制赋值运算符。
下面的代码替换了您从示例中省略的位,并展示了如何生成一堆 Frame *
而不是 Frame
。基本上,它是您编译问题的解决方法,但如果您的代码需要堆栈使用或者您必须重构太多,它可能不适合您的特定需求。
#include <iostream>
#include <vector>
struct Region{};
struct Frame {
Frame(std::vector<Region> regions_)
: regions(regions_){}
const std::vector<Region> regions;
};
int main(int argc, const char * argv[]) {
std::vector<Frame *> shot;
Frame * currentFrame = new Frame((std::vector<Region>()));
for (int i = 0; i < 10; i++) {
shot.push_back(currentFrame);
currentFrame = new Frame(std::vector<Region>());
}
return 0;
}
另请注意:
how to use const_cast? - const_cast
对你不起作用,会导致 UB。以防万一;)
如果你绝对坚持保持 regions
常量,并有“赋值”,你可以销毁现有的 Frame
并在原地创建一个新的。
std::vector<Frame> shot;
Frame currentFrame = generateRandomFrame();
for (int i = 0; i < length; i++) {
shot.push_back(currentFrame);
currentFrame.~Frame();
new (¤tFrame) Frame(generateNextFrame(shot.back()));
}
然而,更简单的方法是不重新分配任何东西
std::vector<Frame> shot;
shot.push_back(generateRandomFrame());
for (int i = 1; i < length; i++) {
shot.push_back(generateNextFrame(shot.back()));
}
我有以下设置:
struct Frame {
Frame(vector<Region> regions_)
: regions(regions_){}
const vector<Region> regions;
};
现在,在我的代码的不同部分,我想创建一个 vector<Frame>
并创建以下 for
循环:
vector<Frame> shot;
Frame currentFrame = generateRandomFrame();
for (int i = 0; i < length; i++) {
shot.push_back(currentFrame);
currentFrame = generateNextFrame(currentFrame); // this line gives the error
}
其中 generateNextFrame
具有以下签名:
Frame FrameGenerator::generateNextFrame(Frame previousFrame)
现在,这段代码无法编译并出现以下错误:
copy assignment operator of 'Frame' is implicitly
deleted because field 'regions' has no copy assignment
operator const vector<Region> regions;
现在,我不完全理解这个错误信息。我强烈认为这与 currentFrame
分配在 堆栈 而不是 堆 上有关,因此我可以'只是重新分配变量。然而,作为 C++ 的新手,我不熟悉如何处理这些情况。我应该在这里改用指针并尝试在堆上分配 currentFrame
吗?
明确地说,我的目标是生成一系列 frames
(这取决于之前的一些帧)。谁能给我指出正确的方向?
更新:
非常感谢评论中的所有提示,我现在明白问题出在我将 regions
声明为 const
。我重写了代码以使用指针而不是堆变量,现在看起来像这样:
vector<Frame> shot;
Frame currentFrame = generateRandomFrame();
Frame *currentFramePtr = ¤tFrame; // the first frame in the shot is random
for (int i = 0; i < length; i++) {
shot.push_back(*currentFramePtr);
Frame tmpFrame = generateNextFrame(*currentFramePtr);
currentFramePtr = &tmpFrame;
}
这段代码现在可以编译,但是它仍然没有达到我想要的效果。根据我的理解,它现在应该可以工作了,因为我将 currentFrame
存储在一个指针中,所以我可以很容易地用我创建的新对象覆盖它。但似乎仍然存在一个错误,帧生成没有按预期工作(即生成的任何新帧都带有 0 个区域,而区域数量应与前一帧相同)。任何人都可以看到我的代码的这个更新版本有什么问题吗?
您的 struct
声明了一个 const
成员,由于 const
成员没有复制赋值运算符,这会强制编译器隐式删除默认的复制赋值运算符。
下面的代码替换了您从示例中省略的位,并展示了如何生成一堆 Frame *
而不是 Frame
。基本上,它是您编译问题的解决方法,但如果您的代码需要堆栈使用或者您必须重构太多,它可能不适合您的特定需求。
#include <iostream>
#include <vector>
struct Region{};
struct Frame {
Frame(std::vector<Region> regions_)
: regions(regions_){}
const std::vector<Region> regions;
};
int main(int argc, const char * argv[]) {
std::vector<Frame *> shot;
Frame * currentFrame = new Frame((std::vector<Region>()));
for (int i = 0; i < 10; i++) {
shot.push_back(currentFrame);
currentFrame = new Frame(std::vector<Region>());
}
return 0;
}
另请注意:
how to use const_cast? - const_cast
对你不起作用,会导致 UB。以防万一;)
如果你绝对坚持保持 regions
常量,并有“赋值”,你可以销毁现有的 Frame
并在原地创建一个新的。
std::vector<Frame> shot;
Frame currentFrame = generateRandomFrame();
for (int i = 0; i < length; i++) {
shot.push_back(currentFrame);
currentFrame.~Frame();
new (¤tFrame) Frame(generateNextFrame(shot.back()));
}
然而,更简单的方法是不重新分配任何东西
std::vector<Frame> shot;
shot.push_back(generateRandomFrame());
for (int i = 1; i < length; i++) {
shot.push_back(generateNextFrame(shot.back()));
}