c ++使用string :: size创建一个数组

时间:2017-04-19 23:25:18

标签: c++ arrays

我试图用字符串:: size成员创建一个数组,但它在" char message [msgSize]"的声明中抱怨表达式没有评估常量。

然而它让我宣布" msgSize"。

这怎么可能?为什么我被允许做一个常数,但我不允许将它用于需要const的东西。

如果答案是:"字符串的大小可能会改变"然后可以使用sizeof()进行相同的参数,但这样可行。

const unsigned int msgSize = 
        saveAs.size() +
        sizeof("NOTE|  sent get request to: ") + 10;

    char message[msgSize];
    memset(message, 0, msgSize);
    sprintf_s(message, msgSize,"NOTE| sent get request to: %s", saveAs.c_str());
    _cRec->output(message);

5 个答案:

答案 0 :(得分:1)

const只是意味着你保证价值不会改变。您甚至可以使用const_cast覆盖它。

编译器需要什么,可以在编译时评估一个值。这是一个更强烈的要求。此类值标有constexpr关键字。

不幸的是,std::string让你感到不快...... size()不是constexpr

我玩following example

#include <iostream>
#include <string>
using namespace std;

const string msg("Some msg");
constexpr int msg_len = msg.size();

int main() {

    char msg[msg_len];

    cout << sizeof(msg);
    return 0;
}

问题是size()不是constexpr,你不能使string成为constexpr,因为它有一个非平凡的析构函数。

为什么这样设计是超出我的。似乎是反直觉和严重的限制。但是,有string的非常聪明的实现,例如小存储优化。可能很难让他们constexpr在实施中发生严重变化。

答案 1 :(得分:0)

您必须使您的阵列动态化。 compile 时不知道字符串的大小,但仅在运行时。

此外,您的商家信息不是最小的可编辑示例。我只能假设saveAs是一个std :: string。

以下方法可行:

int main()
   {
        std::string myString("My string");
        char * myCStyleString = new char[myString.size()];

        delete[] myCStyleString;
   }

因为我们动态地在那里分配一个数组。

你想做什么?看起来您只想将文件名复制到消息字符串中。继续使用std :: string;

   int main()
   {
        std::string myString("My string");
        std::string message = "I like beans and rice with: ";
        message += myString;

        return 0;
   }

但同样,我需要一个最小的可编辑示例来确定您的目标。

答案 2 :(得分:0)

  

为什么我可以保持常数,但我不允许使用它   需要const的东西。

这是因为&#34;常数&#34;您拥有的表达式由非常量部分组成,即字符串类的大小方法。就编译时具有已知值而言,它并不是真正的常量。

考虑将来使用constexpr变量/函数

  

如果答案是:&#34;字符串的大小可能会改变&#34;那么   可以使用sizeof()进行相同的参数,但是可行。

不能将相同的参数用于sizeof,因为sizeof不需要它作为常量。

如果您知道saveAs包含已知大小的字符串这一事实,那么最好将该大小声明为常量然后在计算中引用它:

constexpr unsigned int msgSize = 
        SAVEAS_SIZE +
        sizeof("NOTE|  sent get request to: ") + 10;

然后这将允许你这样做:

char message[msgSize];

答案 3 :(得分:0)

在C ++中,您无法声明VLA s。

声明数组时,例如:

char message[x];

表达式x必须在compile time处有价值,因为在编译源代码时,它的值必须是众所周知的。

在你的例子中:

char message[msgSize];

表达式(变量)msgSize在编译时是未知的,但仅在运行时。那是因为编译器必须知道堆栈中保留了多少字节。

注意:变量msgSize常量值。常量值表达式在编译时计算。它只是意味着一旦分配了它的值就不会改变。

在C ++ 11中引入了关键字constexpr,以便定义一个应该在编译时进行评估的表达式。

但是在您的情况下,无法在编译时获取动态字符串的大小。所以你要做的就是使用动态数组(动态内存)。

char* message = new char[msgSize];
// now you have an array of msgSize lenght
// ... do stuff...
// do not forget to release the memory when end
delete[] message;

最后,我建议你重新详细说明你的代码,因为你可能不需要动态的字符数组,只需要std::string。实际上,您可以使用重载的运算符+来连接字符串,并使用方法std::string::c_str()来访问const char*以实现向后兼容性。

答案 4 :(得分:0)

你需要一个带有char message[msgSize];编译时常量,因为这是一个局部变量,它使用在数据段中分配的静态内存,所以编译器需要计算代码所需的字节数,包括局部变量和数组。

您可以使用动态内存来解决问题。 动态内存在堆中分配。在C中,您应该使用malloc()。在C ++中,您应该使用new[](或更好,std::vector,甚至std::string)。然后,您可以使用变量中的运行时值指定内存大小。

因此,您的代码看起来更像是以下内容:

char* message = new char[msgSize]; //Allocated memory
//Do everything that you need...
delete[] message; //Release memory

或者:

#include <vector>

std::vector<char> message(msgSize); //Allocated memory
//Do everything that you need...