2016-11-15 3 views
1

У меня есть то, что я считал простыми. Объявления в заголовке класса:Попытка создать Qt 4.7 QStrings, материал в массив указателей

public: 
    int index;   // just your vanilla integer 
    QString *qspointer; // allocated array with space for 1000 pointers 
    // allocation occurs first thing in class code: it's definitely there 

код:

index = 0;      // works 
qspointer[index] = new QString(); // causes error 

альтернативный код

QString *qs;      // works 
qs = new QString();    // works 
qspointer[index] = qs;   // causes error 

Ошибка компиляции в любом случае:

"invalid conversion from QString to char" 
"initializing argument 1 of 'QString& QString::operator=(char)" 

это указатель QString. У меня есть массив указателей QString. Я просто хочу поместить указатель в массив указателей. Это отлично работает с неклассическими элементами, такими как указатели int, указатели символов и т. Д. Это похоже на то, что это не массив указателей QString. Но ... рядом, у меня есть этот код:

qspointers[index].~QString(); // compiler likes this. 

Что ... если это не массив QString указателей ... должно вызвать ошибку. Но это не так. Я так растерялся. :)

Мне явно не хватает чего-то фундаментального; оценят любые указатели (ха)

+2

Указатель 'QString *' указывает на массив 'QString', а не массив' QString * '. 'qspointer [index]' является 'QString'. Почему бы вам просто не использовать QStringList или подобное? –

+1

Тот факт, что 'qspointers [index]. ~ QString();' compiles только доказывает, что 'qspointers [index]' является 'QString'. Если бы это был указатель, он не смог бы скомпилировать - вам понадобится qspointers [index] -> ~ QString(); ' –

+0

ph, bloddy foo. :) Спасибо! Лес ... деревья .... – fyngyrz

ответ

1

qspointer[index] = new QString();

qspointer является указателем на QString (ов), которые, возможно, указывает на массив и может быть проиндексированы. Таким образом, qspointer[index] является QString. Точнее, выражение qspointer[index] возвращает ссылку на QString. new QString(); возвращает указатель, так что вы пытаетесь сделать в этой линии выглядит

QString *ptr = whatever; 
QString s = ptr; 

, который, очевидно, ошибка. Аналогично,

qspointer[index] = qs; 

имеет ту же проблему.

У меня есть массив указателей QString.

Похоже, вы этого не сделаете. QString *qspointer; - указатель на массив QString, а не массив указателей.

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

// Declaration: 
QString **qspointer; // Pointer to pointers 

// Allocation: 
qspointer = new QString*[1000]; // Allocated array of 1000 pointers 

// Putting a pointer into the array of pointers: 
qspointer[index] = new QString(); 

Далее,

qspointers[index].~QString();

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

И, наконец, вызов деструктора явно является badidea.Используйте delete для выделенных кучи объектов и delete[] для массивов. Обратите внимание, что с указателем вы не можете определить, указывает ли он на один объект или массив.

1

Учитывая, что QString s являются неявно разделяемыми классами значений (а также поддерживают семантику переноса с Qt 4.8), и что мы используем C++, а не C, а год - 2016 год, последнее, что вам нужно сделать, это возиться с указателями на строки, вроде 1980-х годов.

Вот то, что вы хотите:

QVector<QString> strings(1000); // 1000 empty strings 
strings[0] = "Foo"; 
strings[1] = "Bar"; 
strings.push_back("Moo"); 
Q_ASSERT(strings.back() == "Moo"); 

Это также верно, если вы используете std::string:

QVector<std::string> strings(1000); 
// etc. 

Если массив имеет фиксированный размер, вы должны использовать std::array вместо:

std::array<QString, 1000> strings; 
strings[0] = "Foo"; 
strings[1] = "Bar"; 

Отметьте, что ни один из t он выше код будет медленнее, чем так, как Вы, вероятно, собираетесь это сделать:

QString *strings[1000]; 
strings[0] = new QString("Foo"); 
strings[1] = new QString("Bar"); 

Но это еще не все, конечно. Вы должны убедиться, что строки не просачиваются и, предположительно, что любые нераспределенные строки не являются просто оборванными указателями. И, конечно, вы не хотите, чтобы кто пытается скопировать этот массив вслепую:

// DO NOT EVEN THINK OF DOING IT THIS WAY! 
class MyClass { 
    Q_DISABLE_COPY(MyClass) 
    QString *strings[1000]; 
public: 
    MyClass() { memset(&strings, 0, sizeof(strings)); } 
    // Note: calling delete with a null pointer is perfectly safe 
    ~MyClass() { for (auto string : strings) delete string; } 
    void setString(int index, const QString & value) { 
    if (!strings[index]) 
     strings[index] = new QString(value); 
    else 
     *strings[index] = value; 
    } 
    QString string(int index) const { 
    return strings[index] ? *strings[index] : QString(); 
    } 
}; 

Это способ сделать это ужасно абсолютно неуместно в 2016 году Если ваша платформа слишком стара, чтобы использовать std::array, использовать QVarLengthArray: это как std::array, который может произвольно динамически изменять размер. И сохраните эти строки по значению, а не указателем!.

Управление жизненным циклом на месте, которое вы делаете, вызывая деструктор и т. Д., Мучительно и имеет абсолютно никакого места вне специализированных классов, которые занимаются управлением ресурсами. Что это означает в простых английских терминах? Это означает, что , если у есть результаты бенчмаркинга, которые показывают, что нормальные контейнеры как-то слишком медленны. и вы определили, что ваши алгоритмы не виноваты, а просто нужен специализированный контейнер для поддержки указанных специализированных алгоритмов , тогда вы должны напишите пользовательский контейнер, который управляет набором строк. И затем используйте этот контейнер в своем коде, с отвращением. В 99,9999% случаев вы не захотите внедрять такой контейнер. Стандартная библиотека и Qt-контейнеры достаточно умны. Используйте их надлежащим образом, и вы должны быть настроены.

+0

Куба, то, что я делаю, прекрасно работает, и 100% отвечает моим потребностям. * Это делает его 100% правильным *. Но спасибо, что нашли время, чтобы опубликовать свою позицию. – fyngyrz

Смежные вопросы