繁体   English   中英

emplace_back和move分配构造函数存在问题

[英]Problems with emplace_back and move assignment constructors

给出以下代码

test.h:

#ifndef __graph_aufbau_header__
#define __graph_aufbau_header__
#include <vector>
#include <queue>
#include <string>

using namespace std;

class Knoten {
    public:
        unsigned int nummer;
        double x_1;
        double x_2;
        unsigned int abstand;

        Knoten(unsigned int num, double x1, double x2) : nummer(num), x_1(x1), x_2(x2), abstand(-1) {};
        Knoten(Knoten&& anderer) : nummer(anderer.nummer), x_1(anderer.x_1), x_2(anderer.x_2), abstand(anderer.abstand) {};
        Knoten& operator=(Knoten&& anderer) = default;
};

class Kante {
    public:
        unsigned int quellknotennum;
        unsigned int zielknotennum;
        unsigned int gewicht;

        Kante(unsigned int qnum, unsigned int znum, unsigned int gew)
        : quellknotennum(qnum), zielknotennum(znum), gewicht(gew)
        {};

        Kante(Kante&& andere)
        : quellknotennum(andere.quellknotennum), 
        zielknotennum(andere.zielknotennum), 
        gewicht(andere.gewicht) {};

        Kante& operator=(const Kante& andere) = default;
        inline bool operator<(const Kante& kante_2){
           return this->quellknotennum < kante_2.quellknotennum;
        };
};

class Offset {
    public:
        unsigned int knoten_num;
        unsigned int kanten_num;

        Offset(unsigned int knnum, unsigned int kanum) 
        : knoten_num(knnum), kanten_num(kanum) 
        {};
        Offset(Offset&& anderer)
        : knoten_num(anderer.knoten_num), kanten_num(anderer.kanten_num) {};

        Offset& operator=(Offset& anderer) = default;
};

class Graph {
    public:
            vector<Knoten> coordList;
            vector<Kante> edgeList;
            vector<Offset> edgeOffsets;
            //vector<unsigned int> abstand;

            Graph() : coordList(), edgeList(), edgeOffsets(){};

            void knoten_einlesen(double x_1, double x_2);
            void kante_einlesen(unsigned int quellknoten, unsigned int zielknoten, unsigned int gewicht);
            void offset_einlesen(unsigned int nummer, unsigned int kante);
            void einlesen(string quelle);
            Knoten naechster_Nachbar(Knoten& knoten);
};

#endif

test.cc:

// kein iostream
#include <fstream>  // benötigt für die Deklaration eines Dateistroms
#include <iostream>
#include <string>
#include <sstream> // zum Splitten
//#include <regex>
#include <cstdlib>   // Zur Umwandlung von Strings in Doubles
#include <algorithm>  // fuer find_if()
#include <queue>
#include <vector>
#include "test.h"

using namespace std;

void Graph::knoten_einlesen(double x_1, double x_2){
    unsigned int neue_position = coordList.size();
    coordList.emplace_back(neue_position, x_1, x_2);
}

void Graph::kante_einlesen(unsigned int knoten_1, unsigned int knoten_2, unsigned int gewicht){
    edgeList.emplace_back(knoten_1, knoten_2, gewicht);
}

void Graph::offset_einlesen(unsigned int nummer, unsigned int kante){
    edgeOffsets.emplace_back(nummer, kante);
}

void Graph::einlesen(string quelle){
    ifstream datendatei(quelle);

    if (datendatei.is_open()){
        string aktuelle_zeile;

        getline(datendatei, aktuelle_zeile);
        unsigned int anzahl_knoten = stoi(aktuelle_zeile);

        getline(datendatei, aktuelle_zeile);
        unsigned int anzahl_kanten = stoi(aktuelle_zeile);

        unsigned int nummer, position;
        for(auto& knoten: coordList){
            nummer = knoten.nummer;
            auto erste_kante = find_if(edgeList.begin(), edgeList.end(), [nummer] (Kante kante)\
            {return nummer == kante.quellknotennum;});
            position = erste_kante - edgeList.begin();   // Position der ersten Kante, die mit dem Knoten verbunden ist, in edgeOffsets
            offset_einlesen(nummer, position);
        }


        datendatei.close();
    }
}

Knoten Graph::naechster_Nachbar(Knoten& knoten){
    return coordList.at(edgeList.at(edgeOffsets.at(knoten.nummer).kanten_num).zielknotennum);
}

,我通过调用g++ -std=gnu++11 test.cc收到以下错误:

test.cc: In member function 'Knoten Graph::naechster_Nachbar(Knoten&)':
test.cc:55:96: error: use of deleted function 'constexpr Knoten::Knoten(const Knoten&)'
         return coordList.at(edgeList.at(edgeOffsets.at(knoten.nummer).kanten_num).zielknotennum);
                                                                                                ^
In file included from test.cc:11:0:
test.h:10:11: note: 'constexpr Knoten::Knoten(const Knoten&)' is implicitly declared as deleted because 'Knoten' declares a move constructor or move assignment operator
     class Knoten {
           ^~~~~~
In file included from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/stl_algobase.h:71:0,
                 from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/char_traits.h:39,
                 from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/ios:40,
                 from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/istream:38,
                 from C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/fstream:38,
                 from test.cc:2:
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/predefined_ops.h: In instantiation of 'bool __gnu_cxx::__ops::_Iter_pred<_Predicate>::operator()(_Iterator) [with _Iterator = __gnu_cxx::__normal_iterator<Kante*, std::vector<Kante> >; _Predicate = Graph::einlesen(std::__cxx11::string)::<lambda(Kante)>]':
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/stl_algo.h:120:14:   required from '_RandomAccessIterator std::__find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Kante*, std::vector<Kante> >; _Predicate = __gnu_cxx::__ops::_Iter_pred<Graph::einlesen(std::__cxx11::string)::<lambda(Kante)> >]'
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/stl_algo.h:161:23:   required from '_Iterator std::__find_if(_Iterator, _Iterator, _Predicate) [with _Iterator = __gnu_cxx::__normal_iterator<Kante*, std::vector<Kante> >; _Predicate = __gnu_cxx::__ops::_Iter_pred<Graph::einlesen(std::__cxx11::string)::<lambda(Kante)> >]'
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/stl_algo.h:3817:28:   required from '_IIter std::find_if(_IIter, _IIter, _Predicate) [with _IIter = __gnu_cxx::__normal_iterator<Kante*, std::vector<Kante> >; _Predicate = Graph::einlesen(std::__cxx11::string)::<lambda(Kante)>]'
test.cc:44:57:   required from here
C:/Program Files/mingw-w64/x86_64-6.2.0-win32-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.2.0/include/c++/bits/predefined_ops.h:234:11: error: use of deleted function 'constexpr Kante::Kante(const Kante&)'
  { return bool(_M_pred(*__it)); }
           ^~~~~~~~~~~~~~~~~~~~
In file included from test.cc:11:0:
test.h:22:11: note: 'constexpr Kante::Kante(const Kante&)' is implicitly declared as deleted because 'Kante' declares a move constructor or move assignment operator
     class Kante {
           ^~~~~
test.cc:43:99: note:   initializing argument 1 of 'Graph::einlesen(std::__cxx11::string)::<lambda(Kante)>'
                 auto erste_kante = find_if(edgeList.begin(), edgeList.end(), [nummer] (Kante kante)\
                                                                                                   ^

(不要错过隐藏在右侧的错误)

我已经尝试了许多小时来解决此问题,而今天,我不知道这里出了什么问题。 显然,代码在方法naechster_nachbar(..)中调用了一个隐式删除的类“ Knoten”的move构造函数-但我不知道为什么会这样以及如何防止出现相应的错误消息。

另一部分(较大的部分,稍微模糊)可能是在函数einlesen(...)(lambda函数?)中的某处引起的,可能是与第一个部分相同的原因引起的。

给定的代码不必能够独立编译,甚至不必完整且有意义。 它的唯一目的是演示所生成的错误消息。 我无法进一步减小此最小示例的大小。 我们被迫使用C ++ 11(因此必须使用命令行选项)。

提前谢谢了!

Knoten Graph::naechster_Nachbar(Knoten&)按值返回,因此尝试复制Knoten 但这不能,因为该类仅具有move构造函数而没有copy构造函数。

有趣的是,move构造函数实际上是从anderer复制所有数据的,因此它可能只是一个复制构造函数。

您已为Knoten和Kante指定了移动构造函数,这使默认副本构造函数被删除。 基本原理是,如果您编写自己的move构造函数,则假定此类需要一些非平凡的逻辑,因此,如果为move构造函数/赋值运算符提供了此逻辑,则常规版本也将需要此逻辑。

如果添加以下内容,则代码将编译:

Knoten(const Knoten& anderer) = default;
Knoten& operator=(const Knoten& anderer) = default;

Kante(const Kante& anderer) = default;

但我不确定默认逻辑是否足以满足您的课程要求。 您还应该考虑是否真的需要自己的移动构造函数/运算符。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM