Странность со структурами, определенными в файлах, отличных от main.cpp - PullRequest
2 голосов
/ 19 июля 2010

Я обнаружил, что структура (с массивом значений типа double и одним целым числом), определенная в отдельном Cpp-файле, но вызываемая из main, отправляет необоснованные значения в cout для массива.Ниже, как я надеюсь, приведен минимальный пример, вместе с выводом на консоль.

Мои извинения за то, что мой код зашифрован - я немного боролся за правильное форматирование.

I 'Буду благодарен, если кто-нибудь поможет мне понять и исправить это.

Бест, Джо

(1) main.cpp:

#include "iostream"
#include "defs.h"

using namespace std;

int main()
{
    MyStruct myModel=ConstructModel();

    cout << endl << "myModel goes first:" << endl;
    for(int i=0; i<myModel.n; i++)
        cout << "myModel.Y[" << i << "]=" << myModel.Y[i] << endl;
    cout << "myModel.n=" << myModel.n << endl;

    MyStruct myOtherModel;
    myOtherModel.n=2; double Y[2]={0.1,0.1};
    myOtherModel.Y=Y;

    cout << endl << "now myOtherModel:" << endl;
    for(int i=0; i<myModel.n; i++)
        cout << "myOtherModel.Y[" << i << "]=" << myOtherModel.Y[i] << endl;

    return 0;
}

(2) defs.cpp:

#include "defs.h"

MyStruct ConstructModel()
{
 MyStruct Model;

 double Y[2]={0.1,0.1}; Model.Y=Y;
    int n=2; Model.n=n;

    return Model;
}

(3) defs.h:

#ifndef DEFS_H  
#define DEFS_H

struct MyStruct
{
    double *Y;//length (n+1)
    int n;
};

MyStruct ConstructModel();

#endif

Консольный вывод

На моей машине (WinXP 32bit, MSVC2008) это дает:

myModel идет первым:

myModel.Y [0] = 1.12947e-307

myModel.Y [1] = 1,80243e-307

myModel.n = 2

теперь myOtherModel:

myOtherModel.Y [0] = 0,1

myOtherModel.Y [1] = 0,1

Ответы [ 5 ]

10 голосов
/ 19 июля 2010

Ваша структура содержит голый указатель на double. В defs.cpp вы инициализируете это локальной переменной. Вне области действия ConstructModel() эта память больше не действительна.

Если вам нужен массив в структуре, вы должны объявить его (включая его размер, который должен быть одинаковым для всех MyStruct с). Но вместо того, чтобы использовать массивы, почему бы вам не использовать, например, std::list<double> или std::vector<double>?

2 голосов
/ 19 июля 2010
MyStruct ConstructModel()
{
  MyStruct Model;

  double Y[2]={0.1,0.1}; 

здесь вы назначаете адрес локального Y[0] на Model.Y:

  Model.Y=Y;
  int n=2; 
  Model.n=n;

  return Model;

здесь локальный Y выходит за рамки и уничтожается, оставляя Model.Y суказатель на несуществующий объект:

}
2 голосов
/ 19 июля 2010

Проблема в том, что массив Y, содержащийся в ConstructModel, действителен только до тех пор, пока выполняется ConstructModel.Вы (косвенно) возвращаете указатель на эту локальную переменную, которая больше не действительна к моменту обращения к ней.

1 голос
/ 19 июля 2010

Когда функция ConstructModel заканчивает работу, массив выходит из области видимости. Попробуйте создать массив в куче.

0 голосов
/ 04 августа 2010

Это не ответ, но еще один вопрос на обратной стороне вышеизложенного.

Если я изменю код на приведенный ниже, указатель, похоже, не выйдет из области видимости, когда структура состоит только из этого одного указателя.Если структура определена как содержащая другое значение (скажем, целое число), адрес теряется.Разве это не говорит о том, что объяснения к моему первому вопросу не являются полной картиной?

Я не уверен, что это кому-нибудь интересно.Я подозреваю, что внутреннее устройство для объявления и определения / выделения структуры является причиной этого явления - возможно, кто-то может подтвердить / объяснить.

#include "iostream"
using namespace std;

struct MyStruct
{
    //int n; // <-- if commented, result is as expected. Else, address is lost.
    double *Y;//length (n+1)
};

MyStruct ConstructModel()
{
    MyStruct Model;
    //int n=2; Model.n=n;
    double Y[2]={0.1,0.1}; Model.Y=Y;
    return Model;
}


int main()
{
    MyStruct myModel=ConstructModel();

    for(int i=0; i<2; i++)
        cout << "myModel.Y[" << i << "]=" << myModel.Y[i] << endl;

    return 0;
}

ОБНОВЛЕНИЕ: Компиляция с g ++ вместо MSVC не показывает разницу в выводе.Похоже, что это зависит от компилятора ...

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