1

类边缘:

class Edge {
    int dist = 0;
    std::pair<Node, Node> ends;
public:
    Edge() = default;
    explicit Edge(const int idist) : dist(idist) { }
    explicit Edge(const int idist, Node& end1, Node& end2) : dist(idist) {
        ends.first = end1;
        ends.second = end2;
    }
    ~Edge() = default;
};

在 ctorexplicit Edge(const int idist, Node& end1, Node& end2)中,为什么我不允许使用语法?:

explicit Edge(const int idist, Node& end1, Node& end2) : dist(idist), ends.first(end1), ends.second(end2) { }
4

3 回答 3

4

这是不允许的。作为成员初始化列表的语法,

class-or-identifier ( expression-list(optional) ) (1) 
class-or-identifier brace-init-list   (2) (since C++11)

虽然ends.firstends.second不引用类或标识符,但它们是表达式。您必须ends整体初始化,例如

explicit Edge(const int idist, Node& end1, Node& end2) : dist(idist), ends(end1, end2) { }
于 2020-08-24T04:26:02.190 回答
1

你试图做的事情是允许的,但你做的方式是不允许的。

初始化器列表指定如何将包含未初始化字节的随机内存位转换为有效对象。然后构造函数可以对这个新对象做一些事情,但是对象状态需要事先初始化。对于默认初始化导致的周围未初始化的值有一些警告,但在初始化列表中唯一有效的事情是调用成员的构造函数。(有关默认初始化的更多信息,请参见此处。)

在您的情况下,first并且second是 a 的字段pair。在构建该对之前,您无法访问它们。即使那样,您也不一定要按照您尝试的方式重新初始化它们。

解决方案是使用其构造函数之一一次初始化整个对:

explicit Edge(const int idist, Node& end1, Node& end2) : dist(idist), ends(end1, end2) { }
于 2020-08-24T04:32:31.353 回答
0

C++ 类的基本特征之一是每个对象(没有恶意)都将由其构造函数正确创建。反过来看,如果一个类型有构造函数,那么你必须使用构造函数创建该类型的对象。

在构造函数初始化列表中Edge,每个成员都Edge被构造。由于std::pair有自己的构造函数,构造一个Edge对象意味着ends使用适当的构造函数构造该成员std::pair

这不是你应该试图绕过的东西。它是健全编程的基础。构造函数创建对象。做你自己的事情有可能创造出没有被正确创造的东西。是的,在这种特殊情况下,您可能可以侥幸逃脱。但是绕过构造函数并没有什么好处,而且在其他情况下,这会导致严重的问题。不要绕过构造函数。让他们做他们的工作,这样你的工作就会容易得多。

于 2020-08-24T13:47:46.370 回答