Почему не вызывается конструктор копирования при инициализации переменной другим объектом?

Рейтинг: 0Ответов: 0Опубликовано: 09.03.2023

Понимаю что исходный код достаточно большой, но все же, надеюсь кто то да подскажет. Пытаюсь разобраться с кодом из книги Lippman С++ Primer, конец 15 главы. Возможно я что то неправильно понимаю, но почему в main в строке:

Query query = Query("she") & Query("is");

копирующий конструктор Query вызывается всего 2 раза при вызове конструктора BinaryQuery, когда происходит инициализация lhs и rhs, но не вызывается когда собственно инициализируется переменная query в функции main? Собственно и не могу понять каким образом инициализируется эта переменная если не при помощи копирующего конструктора.

Как я понял, алгоритм выполнения следующий:

  1. Создается файловый поток
  2. Создается объект класса TextQuery
  3. Вызывается конструктор Query(string) с аргументом "she" (внутри вызывается WordQuery(string))
  4. Вызывается конструктор Query(string) с аргументом "is" (внутри вызывается WordQuery(string))
  5. Вызывается оператор & с двумя аргументами
  6. Вызывается конструктор AndQuery в который передаются оба операнда
  7. Вызывается конструктор BinaryQuery в котором происходит инициализация lhs и rhs с помощью копирующего конструктор Query
  8. Далее вызывается конструктор Query с параметром shared_ptr, после чего q ссылается на AndQuery объект
  9. И вот тут по моему должен вызываться копирующий конструктор Query чтобы произошла инициализация переменной query в функции main, но почему то этого не происходит...

Исходный код:

using namespace std;

class QueryResult
{
public:
    using line_no = vector<string>::size_type;
    QueryResult(string sw, shared_ptr<set<line_no>> ln, shared_ptr<vector<string>> ft) : sought_word(sw), lines_numbers(ln), file_text(ft) {}
    auto begin() const { return lines_numbers->begin(); }
    auto end() const { return lines_numbers->end(); }
    auto get_file() const { return file_text; }
private:
    string sought_word;
    shared_ptr<set<line_no>> lines_numbers;
    shared_ptr<vector<string>> file_text;
};

class TextQuery
{
public:
    using line_no = vector<string>::size_type;
    TextQuery(ifstream& is) : file_text(new vector<string>)
    {
        string line;
        while (getline(is, line))
        {
            file_text->push_back(line);
            istringstream line_stream(line);
            string word;
            while (line_stream >> word)
            {
                auto& lines_numbers = words_map[word];
                if (!lines_numbers) lines_numbers.reset(new set<line_no>);
                lines_numbers->insert(file_text->size() - 1);
            }
        }
    }
    QueryResult query(const string& sought_word) const
    {
        static shared_ptr<set<line_no>> no_data(new set<line_no>);
        auto loc = words_map.find(sought_word);
        if (loc == words_map.end()) return QueryResult(sought_word, no_data, file_text);
        else return QueryResult(sought_word, loc->second, file_text);
    }
private:
    shared_ptr<vector<string>> file_text;
    map<string, shared_ptr<set<line_no>>> words_map;
};

class QueryBase
{
    friend class Query;
protected:
    using line_no = TextQuery::line_no;
    virtual ~QueryBase() = default;
private:
    virtual QueryResult eval(const TextQuery&) const = 0;
    virtual string rep() const = 0;
};

class Query
{
    friend Query operator~(const Query&);
    friend Query operator|(const Query&, const Query&);
    friend Query operator&(const Query&, const Query&);
    friend ostream& operator<<(ostream&, const Query&);
public:
    Query(const string&);
    Query(const Query& query)
    {
        cout << "Here..." << endl;
        q = query.q;
    }
    QueryResult eval(const TextQuery& t) const { return q->eval(t); }
    string rep() const { return q->rep(); }
private:
    Query(shared_ptr<QueryBase> query) : q(query) {}
    shared_ptr<QueryBase> q;
};

ostream& operator<<(ostream& os, const Query& query)
{
    return os << query.rep();
}

class WordQuery : public QueryBase
{
    friend class Query;
private:
    WordQuery(const string& s) : query_word(s) {}
    QueryResult eval(const TextQuery& t) const { return t.query(query_word); }
    string rep() const { return query_word; }
    string query_word;
};

inline Query::Query(const string& s) : q(new WordQuery(s)) {}

class BinaryQuery : public QueryBase
{
protected:
    BinaryQuery(const Query& l, const Query& r, string s) : lhs(l), rhs(r), op_sym(s) {}
    string rep() const { return "(" + lhs.rep() + " " + op_sym + " " + rhs.rep() + ")"; }
    Query lhs;
    Query rhs;
    string op_sym;
};

class AndQuery : public BinaryQuery
{
    friend Query operator&(const Query&, const Query&);
    AndQuery(const Query& left, const Query& right) : BinaryQuery(left, right, "&") {}
    QueryResult eval(const TextQuery& text) const
    {
        auto left = lhs.eval(text);
        auto right = rhs.eval(text);
        auto ret_lines = make_shared<set<line_no>>();
        set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_lines, ret_lines->begin()));
        return QueryResult(rep(), ret_lines, left.get_file());
    }
};

inline Query operator&(const Query& lhs, const Query& rhs)
{
    auto temp = shared_ptr<QueryBase>(new AndQuery(lhs, rhs));
    return Query(temp);
}

int main()
{
    ifstream file("./file.txt");
    TextQuery text_query(file);
    Query query = Query("she") & Query("is"); // ???????????????????????
    print(cout, query.eval(text_query));

    return 0;
}

Ответы

Ответов пока нет.