Структура "сброс" - PullRequest
       22

Структура "сброс"

1 голос
/ 11 ноября 2011

У меня проблемы с пониманием вывода следующего кода:

int main(void)
{
    vector<TreeNode> tree;
    for(int i = 0; i < 50; i++)
    {
        TreeNode node;
        tree.push_back(node);
    }

    for(int i = 0; i < 50; i++)
    {
        Image image;
        image.Path = "TestPath";
        image.Votes = 0;

        TreeNode node = tree.at(i);
        node.images.push_back(image);
        node.images.push_back(image);
    }

    TreeNode node = tree.at(0);
    cout << "TEST" << endl;
    cout << node.images.size() << endl;
}

Выход:

TEST
0

Почему вывод 0 и что я должен сделать, чтобы это исправить? Я ожидаю, что размер будет 2, а не 0. Это, вероятно, как-то связано с тем, как работает структура. Мои две определенные структуры следующие:

typedef struct
{
    string Path;
    int Votes;
} Image;

typedef struct
{
    int treeIndex;
    float centroid;
    vector<float*> features;
    vector<Image> images;
} TreeNode;

Обратите внимание, что я не могу использовать классы вместо структур.

Ответы [ 6 ]

9 голосов
/ 11 ноября 2011

vector :: at возвращает ссылку на объект.

Ваша линия

TreeNode node = tree.at(i);

создает копию TreeNode в узле, поэтому, когда вы добавляете в него изображения, он добавляет их в новый объект, которого нет в вашем векторе.

Если вместо этого вы используете

TreeNode& node = tree.at(i);

Это добавит изображения правильно.

3 голосов
/ 11 ноября 2011

Вы извлекаете узел по значению и изменяете свою локальную копию.Попробуйте

TreeNode &node = tree.at(i);
2 голосов
/ 11 ноября 2011

Ваша проблема в этой строке:

TreeNode node = tree.at(i);

Здесь вы делаете копию узла, хранящегося в контейнере.Ваш последующий код изменяет эту копию, а не оригинал.В конце вы получаете доступ к оригиналу из контейнера, который не изменен.

Вместо этого используйте

TreeNode& node = tree.at(i);

, чтобы node ссылался на объект, сохраненный в векторе.& означает, что узел no - это не объект TreeNode, а ссылка на объект TreeNode.То есть каждый доступ к node фактически будет обращаться к объекту, к которому он был привязан, то есть к объекту, возвращаемому tree.at(i).

Кстати, о вашем коде следует помнить и другие вещи.

Во-первых, вы сказали, что не можете использовать класс, но должны использовать структуру.В C ++ struct и class абсолютно одинаковы, за исключением того, что по умолчанию все элементы имеют открытые члены.То есть следующие два примера кода полностью эквивалентны:

struct X
{
  int i;
  int k;
};

и

class X
{
public:
  int i;
  int k;
};

Действительно, вы можете даже объявить ваш тип вперед с помощью struct, а затем определить его с помощьюclass или наоборот.

Необходимость использования struct вместо class может означать только одну из двух вещей: Либо вам нужно включить файл также в C (который не знает class ключевое слово), но в любом случае вы не могли этого сделать, потому что C не знает ни вектор, ни строку.Или вам нужно, чтобы ваш класс был типом POD (обычные старые данные), но опять же ваши структуры не являются типами POD, потому что они имеют члены не-POD типов string и vector<T>.Другими словами, ваши структуры являются уже классами во всех смыслах этого слова.

В связанном узле, поскольку вы не можете включить определение своих структур в C, естьнет смысла использовать typedef здесь.В C ++

struct Image
{
  string Path;
  int Votes;
};

уже позволяет вам ссылаться на тип с помощью Image (в отличие от C, где вам нужно будет использовать struct Image для ссылки на тип в этом случае).

1 голос
/ 11 ноября 2011
TreeNode node = tree.at(i);
node.images.push_back(image);
node.images.push_back(image);

Здесь вы взяли копию TreeNode с индексом i и добавили к ней материал. Затем копия немедленно уничтожается, так как покидает область видимости.

Вместо этого возьмите ссылку, чтобы вы работали с исходным объектом из контейнера:

TreeNode& node = tree.at(i);
node.images.push_back(image);
node.images.push_back(image);
1 голос
/ 11 ноября 2011
TreeNode node = tree.at(i);

Вы получаете копию узла и изменяете копию, а оригинал остается неизменным.

0 голосов
/ 11 ноября 2011

Почему вы сначала вставляете узлы, а затем модифицируете узлы в векторе? Вы можете вставить узел, как только вы правильно его построили (закончили модифицировать). Вам вообще не нужен первый цикл, и просто вставьте толчок в конец второго цикла

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...