【发布时间】:2018-03-26 09:58:08
【问题描述】:
我正在使用 Visual Studio 2017。最近,因为我不喜欢 C++ 的不符合标准,所以我继续并禁用了选项中的非标准语言扩展。到目前为止,一切都很好。现在我有一个问题。
#include <iostream>
#include <vector>
struct Vertex
{
Vertex(float pos) { }
Vertex(Vertex& other) { }
};
std::vector<Vertex> arrayOfVertices;
int main()
{
arrayOfVertices.emplace_back(7.f);
}
这不会在 Visual Studio 中编译,它给出的唯一错误是:
“编译器发生内部错误”
如果我启用语言扩展,它编译得很好。如果我保持禁用语言扩展并使复制构造函数采用const Vertex&,则它编译得很好。
所以我在一些在线编译器上尝试了 GCC,如果复制构造函数不采用 const 引用参数,它将无法编译,并给出各种错误。似乎最有意义的是:
错误:'Vertex&' 类型的非常量引用的初始化无效 来自“顶点”类型的右值
我认为复制构造函数不必是 const,就我而言,我想修改其他参考中的某些内容。我知道非常量参数不能采用 r 值引用,但我对其进行了测试,结果发现在 vector::emplace_back() 中根本没有调用复制构造函数:
#include <iostream>
#include <vector>
struct Vertex
{
Vertex(float pos)
{
std::cout << "Calling constructor\n";
}
Vertex(const Vertex& other)
{
std::cout << "Calling copy constructor\n";
}
};
std::vector<Vertex> arrayOfVertices;
int main()
{
arrayOfVertices.emplace_back(7.f); // Normal constructor called if const,
// doesn't compile if non-const
auto buff = malloc(sizeof(Vertex)); // Placement new
new (buff) Vertex(7.f); // Normal constructor called whether const
// or non-const. This is what I thought emplace_back did
}
所以我不知道发生了什么。我首先想知道如果没有调用复制构造函数,为什么会发生这种情况,以及在这种情况下是否有办法在我的复制构造函数中使用非常量,即使用vector::emplace_back(),因为它似乎只有使用vector::emplace_back()才会出现这个问题。
【问题讨论】:
-
但是如果通过向量重新分配空间,则必须调用复制/移动构造函数...我想说这里发生的所有事情(可能除了 MS 接受的非 const 复制构造函数)有其合理的理由......
-
@在必须重新分配向量的情况下,将使用位于旧容器中的左值调用复制构造函数。
-
请记住,如果复制构造函数可以更改由左值引用引用的旧对象,那将是非常不可取的
-
请注意,MS 标准库的维护者 Stephan Lavavej 曾多次表示
/Za开关测试不佳,标准库并不真正支持。 -
另一件事是没有任何充分的理由拥有非常量复制构造函数。使用
mutable类成员可能是一个更好的解决方案,无论你有什么动机
标签: c++ c++11 copy-constructor const-reference