【问题标题】:Instantiation of a vector of type with no operator=实例化类型为无运算符 = 的向量
【发布时间】:2018-03-26 21:45:12
【问题描述】:

我正在尝试制作 DataEntry 对象的向量,这些对象的 operator= 已禁用:

using Row = vector<DataEntry>;

class DataTable {
public:
    vector<Row> data;
};

这会导致错误

在成员函数 'std::__1::vector<:__1::vector std::__1::allocator> >, std::__1::allocator<:__1:: std::__1::allocator> > > >::operator=' 在这里请求 类数据表 {

有没有办法解决这个问题并在不意外使用operator= 的情况下制作矢量?

【问题讨论】:

    标签: c++ vector


    【解决方案1】:

    有没有办法解决这个问题并在不意外使用 operator= 的情况下制作矢量?

    不,没有。

    T 对std::vector 的要求之一是:

    T 必须满足 CopyAssignable 和 CopyConstructible 的要求。

    如果您能够使用支持 C++14 或 C++17 的编译器,则要求不那么严格。

    对元素的要求取决于对容器执行的实际操作。一般要求元素类型是完整类型,满足Erasable的要求,但很多成员函数要求更严格。

    【讨论】:

    【解决方案2】:

    从 C++11 开始,对元素 depend on the actual operations performed on the container 的要求是,只要您避免任何可能分配给元素的操作,您就可以使用 std::vector&lt;DataEntry&gt;。我相信这包括调整向量大小的任何操作,因为调整大小可能会导致重新分配,这需要将现有元素分配给新元素。

    这是一个使用std::vector&lt;DataEntry&gt; 的示例,其中DataEntry 是不可复制和不可分配的。我只是确保std::vector 被初始化为正确的大小:

    #include <vector>
    #include <iostream>
    
    class DataEntry {
    public:
      int value;
      DataEntry() = default;
      DataEntry(const DataEntry&) = delete;
      DataEntry& operator=(const DataEntry&) = delete;  
    };
    
    using Row = std::vector<DataEntry>;
    
    class DataTable {
    public:
      std::vector<Row> data;
      DataTable(size_t rowCount, size_t columnCount) : data(rowCount) {
        for(auto& row : data) {
          row = Row{columnCount};
        }
      }
    };
    
    int main() {
      DataTable table(4, 3);
      table.data[2][1].value = 2;
      std::cout << table.data[3][2].value << "\n"; 
      std::cout << table.data[2][1].value << "\n";
    }
    

    Live demo.

    您对DataEntry 不可分配有什么要求?也许DataEntry 可能是movable?这会给你更多的选择。

    【讨论】:

      【解决方案3】:

      您可以将vector&lt;DataEntry&gt; 更改为vector&lt;DataEntry*&gt; 等,其中包含所有含义。这将允许您创建向量并且仍然没有对 DataEntry 的赋值操作,并以某种方式“保护”它免受意外赋值,但是这当然适用于 DataEntry 而不是向量使用的 DataEntry*,所以它当然不会阻止你不小心做data[4] = nullptr。

      【讨论】:

      • 工作就像一个魅力!非常感谢!
      • 对此要小心,因为将一个vector&lt;DataEntry*&gt; 分配给另一个(例如在编译器为DataTable 生成的operator= 中)将照原样复制DataEntry* 指针,并且具有多个@ 987654330@ 对象引用相同的DataEntry 对象可能不是您想要的。
      • @M.Dow:这对您来说似乎是一个不错的简单解决方案,但老实说,这可能不是您想要做的。拥有一个指针容器只会带来更多问题,其中许多问题很微妙。为什么不让您的数据类型可分配?在移动语义的世界中,这几乎总是可行的。例外情况是您一开始就不应该包含的流之类的东西。
      • @M.Dow:如果它有魅力,现在请关注with all implications of it 部分。我真心的。雷米是对的,因为使用原始指针可能会很棘手。我不知道您的经验如何,但至少考虑将 vector&lt;DataEntry*&gt; 更改为 vector&lt;unique_ptr&lt;DataEntry&gt;&gt; 或 shared_ptr 以确保正确的项目生命周期管理。
      猜你喜欢
      • 2013-05-05
      • 2022-01-13
      • 2015-05-29
      • 2013-10-19
      • 2022-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多