C++ 两种情况下的输出不应该相同吗?

C++ 两种情况下的输出不应该相同吗?,c++,dev-c++,C++,Dev C++,注意代码1中“len=strlen(s);”行中的两个代码的区别:它写在“strcpy(str,s)”之前,而在代码2中它写在后面。这有什么区别?我在DeV C++中运行了我的代码,我得到了不同的输出。两种情况下的输出不应该相同吗 代码1: 代码2: #include <iostream> #include <string.h> using namespace std; class String{ private: char str[];

注意代码1中“len=strlen(s);”行中的两个代码的区别:它写在“strcpy(str,s)”之前,而在代码2中它写在后面。这有什么区别?我在DeV C++中运行了我的代码,我得到了不同的输出。两种情况下的输出不应该相同吗

代码1:

代码2:

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

class String{
    private:
        char str[];
        int len;
    public:
        String()
        {
            cout << "Default Constructor" << endl;
            len = 0;
            strcpy(str,"");
        }
        String(char s[])
        {
            cout << "parameterised constructor" << endl;
            strcpy(str,s);
            len = strlen(s);
        }
        void print()
        {
            cout << str << " len = " << this->len << " strlen = " << strlen(str) << endl;
        }
};

int main()
{
    String str2("Hello World");
    str2.print();
    return 0;
}

代码是错误的,因此输出实际上是未定义的。您可以定义
charstr[]
但在任何时候都不会分配内存缓冲区来保存要复制的字符串的内容。在某些情况下,此代码可能会崩溃

更好的定义:
char*str

在构造器中:

str=newchar[len+1]


另外,不要忘记在析构函数中删除[]str

代码是错误的,因此输出实际上是未定义的。您可以定义
charstr[]
但在任何时候都不会分配内存缓冲区来保存要复制的字符串的内容。在某些情况下,此代码可能会崩溃

更好的定义:
char*str

在构造器中:

str=newchar[len+1]

另外,不要忘记在析构函数中删除[]str
问题在于:

char str[];

这是一个零长度数组(标准C++中的BTW,不能有零长度数组)。 此数组最多可以包含0个字符,因此在您的情况下,零长度数组是毫无意义的

基本上,您正在覆盖不属于您的内存,并且两个程序的行为都未定义。由于行为是未定义的,所以解释两个版本的输出为何不同也是毫无意义的

尝试使用此选项,您可以拥有大小不超过100的字符串:

char str[100];

在C++中使用字符串时,你应该使用<代码> STD::String >原始C字符串。

< P>问题在这里:

char str[];

这是一个零长度数组(标准C++中的BTW,不能有零长度数组)。 此数组最多可以包含0个字符,因此在您的情况下,零长度数组是毫无意义的

基本上,您正在覆盖不属于您的内存,并且两个程序的行为都未定义。由于行为是未定义的,所以解释两个版本的输出为何不同也是毫无意义的

尝试使用此选项,您可以拥有大小不超过100的字符串:

char str[100];

<>在C++中使用字符串,你应该使用<代码> STD::String >原始C字符串。

OOP,C++中应该避免不完整的数组!

class String{
    private:
        char str[];
        int len;
至少应该引起一些警告,因为您声明了一个不完整的数组(大小为0!),它不是纯旧数据(类C)结构的最后一个成员。即使不是语法错误,也不能在该数组中存储任何内容。如果您尝试,您将覆盖下一个成员的内容,在这里
len
。顺便说一句,这就是你得到不一致结果的原因

可以做些什么

< >存储字符串的C++惯用方法是…代码>标准::字符串
,但它在本机类上为您提供了一个过于简单的包装器

class String {
private:
    std::string str;
如果可以的话,第二种简单的方法是声明一个足够大的数组。这就是所谓的懒惰C方式。这里没有分配问题:

#define SIZE 1024
...
class String {
private:
    char str[SIZE];
    int len;
如果您足够勇敢,您可以在类中管理显式分配:在构造函数中分配内存,在析构函数中释放内存。但这意味着您需要立即使用非默认的复制/移动构造函数和赋值运算符,因为您现在需要指定哪个对象拥有分配的数据,并且不再依赖于默认实现

class String {
private:
    char *str;
    int len;

public:
    String()
    {
        cout << "Default Constructor" << endl;
        len = 0;
        str = nullptr;
    }
    String(char s[])
    {
        cout << "parameterised constructor" << endl;
        len = strlen(s);
        str = new char[len + 1];
        strcpy(str, s);
    }
    ~String() {                      // dtor
        if (str != nullptr) delete[] str;
    }
    String(const String&other) {
        cout << "copy constructor" << endl;
        len = other.len;
        str = new char[len + 1];
        strcpy(str, other.str);
    }
    String(String&& other) {
        cout << "move constructor" << endl;
        len = other.len;
        str = other.str;             // take ownership
        other.str = nullptr          // other dtor shall not release!
    }
    String& operator = (const String& other) {
        cout << "copy assignment" << endl;
        String tmp = other;
        str = tmp.str;
        len = tmp.len;
        tmp.len = nullptr;
        return *this;
    }
    String& operator = (String&& other) {
        cout << "move assignment" << endl;
        str = other.str;
        len = other.len;
        other.len = nullptr;
    }
    void print()
    {
        cout << str << " len = " << this->len << " strlen = " << strlen(str) << endl;
    }
};
类字符串{
私人:
char*str;
内伦;
公众:
字符串()
{

CUT< P> OOP,C++中不可避免的不完整数组!
class String{
    private:
        char str[];
        int len;
至少应该引起一些警告,因为您声明了一个不完整的数组(大小为0!),它不是普通旧数据(类C)的最后一个成员结构。即使不是语法错误,也不能在该数组中存储任何内容。如果尝试,将覆盖下一个成员的内容,这里是
len
。顺便说一句,这就是导致结果不一致的原因

可以做些什么

存储字符串的C++习惯用法是……代码> STD::String ,但它给了本地类的简单包装。

class String {
private:
    std::string str;
如果可以的话,第二种简单的方法是声明一个足够大的数组。这就是所谓的惰性C方法。这里没有分配问题:

#define SIZE 1024
...
class String {
private:
    char str[SIZE];
    int len;
如果您足够勇敢,您可以在类中管理显式分配:您在构造函数中分配内存,并在析构函数中释放内存。但这意味着您立即需要非默认的复制/移动构造函数和分配运算符,因为您现在需要指定哪个对象拥有分配的数据,并且不再依赖于default实现

class String {
private:
    char *str;
    int len;

public:
    String()
    {
        cout << "Default Constructor" << endl;
        len = 0;
        str = nullptr;
    }
    String(char s[])
    {
        cout << "parameterised constructor" << endl;
        len = strlen(s);
        str = new char[len + 1];
        strcpy(str, s);
    }
    ~String() {                      // dtor
        if (str != nullptr) delete[] str;
    }
    String(const String&other) {
        cout << "copy constructor" << endl;
        len = other.len;
        str = new char[len + 1];
        strcpy(str, other.str);
    }
    String(String&& other) {
        cout << "move constructor" << endl;
        len = other.len;
        str = other.str;             // take ownership
        other.str = nullptr          // other dtor shall not release!
    }
    String& operator = (const String& other) {
        cout << "copy assignment" << endl;
        String tmp = other;
        str = tmp.str;
        len = tmp.len;
        tmp.len = nullptr;
        return *this;
    }
    String& operator = (String&& other) {
        cout << "move assignment" << endl;
        str = other.str;
        len = other.len;
        other.len = nullptr;
    }
    void print()
    {
        cout << str << " len = " << this->len << " strlen = " << strlen(str) << endl;
    }
};
类字符串{
私人:
char*str;
内伦;
公众:
字符串()
{

不能将代码片段浓缩到只显示感兴趣的片段的最小版本(不同的
strlen
strcpy
调用和输出)可能会改进您的问题。非常确定这是未定义的行为,您可以在不分配所需内存或任何东西的情况下进行strcpy。将代码片段浓缩到只显示感兴趣的片段的最小版本(不同的
strlen
strcpy
调用和输出)可能会改善您的问题。非常确定这是未定义的行为,您可以在不分配所需内存或任何内容的情况下执行strcpy。不要忘记nul终止符
str=new char[len+1];
不要忘记nul终止符
str=new char[len+1];