gpt4 book ai didi

c++ - 在通过引用将 const 成员传递给类时尝试引用已删除的函数

转载 作者:行者123 更新时间:2023-11-30 02:13:38 43 4
gpt4 key购买 nike

这是对问题 attempting to reference a deleted function when passing by reference with a const member 的一种扩展

我读了它并且我确实理解了关于 MoveConstructible 的解释(或者至少,我相信),但是我无法弄清楚为什么,给出以下代码:

struct vertex {
const double x;
const double y;
const double z;
};

const std::vector<vertex> test_vertices()
{
std::vector<vertex> vertices;

vertices.emplace_back(vertex(-3.0, -3.0, 0.0));
vertices.emplace_back(vertex(3.0, -3.0, 0.0));
vertices.emplace_back(vertex(0.0, 0.0, 1.5));
}

此代码完美运行:

std::vector<vertex> panel_vertices = test_vertices();
draw(panel_vertices);

但此其他代码没有并返回“C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.23.28105\include\xutility(1762,1): error C2280: 'p_geometry::vertex &p_geometry::vertex::operator =(const p_geometry::vertex &)': attempted to reference a deleted function"(忽略命名空间,它们在代码中没问题):

class PanelView {

std::vector<vertex> vertices;
public:

PanelView(int x, int y, int w, int h, const char* l = 0);
void setVertices(const std::vector<vertex>& vertices): vertices(vertices) {};
void draw() {
other_draw(vertices);
};
};

我这里没有排序运算符,但除此之外,我还遗漏了一些东西,因为两个代码片段似乎都在做同样的事情。

更新

在您回复(谢谢!!)后,我试图澄清我的想法和疑虑。我尝试了几种配置,我可以得到当有 const 成员时复制运算符被删除(恕我直言,这是一种非常愚蠢的行为,因为当你创建一个拷贝时,你并没有试图修改原始文件中的任何内容,但那是在这个问题的范围)。

我得出了以下四种情况 [1, 2, 2bis, 3]:

#include <iostream>

struct vertex {
const double x;
const double y;
const double z;
};

const std::vector<vertex> test_vertices()
{
std::vector<vertex> vertices;
vertices.push_back(vertex {-3.0, -3.0, 0.0});
vertices.emplace_back(vertex{3.0, -3.0, 0.0});
vertices.emplace_back(vertex{0.0, 0.0, 1.5});
return vertices;
}

class PanelView {
std::vector<vertex> mvertices;
std::vector<vertex> *mvpointer;
public:

//[1] PanelView(const std::vector<vertex>& vertices): mvertices(vertices) {};
//[2] void setVertices(const std::vector<vertex>& v) {mvertices = v; };
//[2 bis] void setVertices(std::vector<vertex> v) {mvertices = v; };
//[3] void setVerticesPointer(std::vector<vertex> *v) {mvpointer = v; };
void draw() {std::cout<<mvertices[0].x; };
void drawp() {std::cout<<(*mvpointer)[0].x; };
};


int main()
{

std::vector<vertex> panel_vertices = test_vertices();

//[1] Works fine
//PanelView pv(panel_vertices);
//pv.draw();

//[2 and 2 bis] - Error C2280: 'vertex &vertex::operator =(const vertex &)': deleted
//PanelView pv;
//pv.setVertices(panel_vertices);

//[3] - OK
PanelView pv;
pv.setVerticesPointer(&panel_vertices);
pv.drawp();


std::cout<<panel_vertices[0].x;
}

PanelView 构造函数 [1] 和 setVertices 方法 [2 和 2 之二] 做同样的事情,将“const std::vector& vertices”作为输入并将它(或什么?)复制到类属性“std”::vector mvertices;”。

第一个疑惑:为什么 setVertices 方法失败了,而构造函数却没有? “幕后”有什么区别?

第二个疑问:我一直认为在C++中引用传递和指针传递基本相同,但是引用传递更C++风格,避免了所有的样板代码,使它更可读。为什么编译器提示 [2(通过引用)],但对 [3 with pointers] 没问题?

最佳答案

简单的答案是,在您的示例中 operator= - 已删除 - 未被调用,这就是它起作用的原因。对比一下:

setVertices(const std::vector<vertex>& v)

获取一个现有的 vector ,然后复制每个值,一个一个地,到一个新的 vector 顶点中。好吧,至少这是编译器尝试生成的代码,类似于:

vertices.reserve(v.size);
for (size_t i = 0; i < v.size(); ++i) {
vertices[i] = v[i];
}

请注意,上面的代码需要一个 operator= 来分配 vertices[i] = v[i];另外,请注意 :) 这不是 STL 将生成的实际代码 - 它仅用于说明预期 operator= 的位置。实际代码最有可能使用通用复制算法和迭代器。

关于您的示例 - vertices.emplace_back(vertex(0.0, 0.0, 1.5)); 不需要 operator= 因为它调用复制构造函数 - 我相信默认生成。通过放置 new 调用复制构造函数。

关于c++ - 在通过引用将 const 成员传递给类时尝试引用已删除的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59023094/

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