GNU C++无法创建常量自定义类实例的向量

3

我有一个非常简单的演示程序,可以在Microsoft Visual C++上编译成功:

#include <cstdio>
#include <vector>
#include <string>

using namespace std;

class String
    :public wstring
{
public:
    String(void)
    {
    }

    String(const String &other)
        : wstring(other)
    {
    }
};

int main(void)
{
    vector<const String> v;
    v.push_back(String());
    printf("Hello, World!");
    return 0;
}

它创建了一组常量字符串向量。然而,在GNU C++ 4.8.2中,它给出了很多错误,试图表明创建常量String对象的向量是不可能的。当我用vector<String>替换vector<const String>时,它可以编译通过。 这样GNU C++的行为的原因是什么?


2
对于某些操作,类型必须是可赋值的(和/或移动变量)。 const T 不满足这一点。 - juanchopanza
2个回答

5

std::vector在内存管理方面处理您的类的实例有其特定方式。它对数据执行的某些操作需要复制构造函数和赋值运算符或noexcept移动构造函数/赋值运算符。 GCC不会编译没有这些内容的示例,这是正确的。 const T不能成为std::vector的有效类型。


4
标准库容器使用分配器。对于支持分配器的容器类型X及其分配器AX::value_typeA::value_type必须相同。由于您的X::value_typeconst String,所以A::value_type也将是const String。然而,标准仅定义具有"value_type"的分配器为“任何非常量、非引用对象类型”(表27 [allocator.requirements])。对于具有const类型的分配器的要求未定义,因此仅尝试创建具有const值类型的容器将导致未定义行为。
此外,许多容器操作需要值类型可复制/可移动赋值,因此您可能无法成功使用它。

未定义行为?楼主说这是编译时错误。 - Karoly Horvath
2
@KarolyHorvath 代码出现未定义行为后报错是完全合理的。 - Joseph Mansfield
谢谢,你一定是对的;GNU不能编译代码而MSVC可以编译它,这表明它确实是“未定义”的行为,因此微软决定允许它编译而不允许GNU编译。 - Vitalii
@VASoftOnline:这非常奇怪,我无法想象微软做了什么会导致它编译失败。 - Mooing Duck
@Mooing Duck 我不确定,但我主要是Windows程序员,有时会将应用程序从Windows移植到Linux;Visual C++在编译过程中可以修复一些错误,因为我有很多例子,软件使用VC++编译并且运行数月而没有问题,而GCC则无法编译。我认为当我在VC++中写vector<const String>时,它可能会默默地忽略const并像vector<String>一样编译,所以程序员甚至可能不知道这是我的例子中的问题。 - Vitalii

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接