c++ - 通过引用返回/传递动态分配的对象

标签 c++ return-by-reference

我现在在我的抽象数据类型中遇到了这个问题。基本上它应该像通常在 C++ 中的字符串类,所以不要被我的 ADT 中的数字弄糊涂了。 我在创建动态分配的对象时遇到问题。 (我相信在下面的代码中正确实现了)然后我需要调用具有对 String346 对象的引用的 concat 函数。

同样在这段代码中,我应该返回一个引用。如果有人可以向我解释这个概念,说明如何使用它以及我将如何以正确的方式返回它,请告诉我,因为我在我的许多函数中返回了对 String346 的引用。

这是重载/默认构造函数(数据是 char *sizeunsigned int):

String346::String346(const char * oldString = "") : size(strlen(oldString)) {
        strcpy(data, oldString);
    }

这是我的 concat 函数的代码,用于传递一个 String346 对象(没有写任何东西,因为我还没有计划如何我想这样做):

String346 & String346::concat(const String346 & catString){

    }

这是我感到困惑的地方。这是我使用 char 指针的 concat 函数。当前段 concat(&newCatString); 是错误的,不适用于上述功能。:

    String346 & String346::concat(const char * catString){
    String346 * newCatString = new (std::nothrow) String346(catString);
    concat(&newCatString);
}

如果您还需要什么,请告诉我。我相信这就是您所需要的,您不需要了解更多。

最佳答案

你的想法是错误的。您不会动态分配新对象。您动态(重新)分配被分配/连接到的对象的数据,然后返回对该对象的引用,而不是对新分配对象的引用。

如果你真的想在一个类似字符串的类中手动实现它(而不是使用标准的 std::string 类),那么尝试更像这样的东西:

class String346 {
private:
    char *data;
    unsigned int size;

public:
    String346();
    String346(const char *oldString);
    String346(const String346 &oldString);
    ~String346();

    //...

    String346& operator=(const String346 &newString);

    //...

    String346& concat(const String346 &catString);

    //...
};

String346::String346() : data(NULL), size(0) {
}

String346::String346(const char * oldString) : data(NULL), size(std::strlen(oldString)) {
    data = new char[size+1];
    std::copy_n(oldString, size, data);
    data[size] = 0;
}

String346::String346(const String346 &oldString) : data(NULL), size(oldString.size) {
    data = new char[size+1];
    std::copy_n(oldString.data, size, data);
    data[size] = 0;
}

String346::~String346() {
    delete[] data;
}

String346& operator=(const String346 &newString) {
    String346 tmp(newString);
    std::swap(data, tmp.data);
    size = tmp.size;
    return *this;
}

String346 & String346::concat(const String346 &catString) {
    String346 tmp;
    tmp.size = size + catString.size;
    tmp.data = new char[tmp.size+1];
    std::copy_n(data, size, tmp.data);
    std::copy_n(catString.data, catString.size, tmp.data+size);
    tmp.data[tmp.size] = 0;
    std::swap(data, tmp.data);
    size = tmp.size;
    return *this;
}

从技术上讲,您不必实现 operator=()concat()char* 版本,因为它们都采用const String346& 作为输入,String346 有一个接受 char* 作为输入的构造函数。如果您将 char* 传递给其中之一,编译器将自动为您构造和销毁一个临时的 String346 对象:

String346 s;
s = "hello"; // calls s.operator=(String346("hello"))...
s.concat("world"); // calls s.concat(String346("world"))...

不过,出于优化目的,这样做可能是有意义的,以避免不必要的临时内存分配(除非您在 C++11 中实现移动语义):

class String346 {
private:
    char *data;
    unsigned int size;

public:
    String346();
    String346(const char *oldString);
    String346(const String346 &oldString);
    ~String346();

    //...

    String346& operator=(const char *newString);
    String346& operator=(const String346 &newString);

    //...

    String346& concat(const char *catString);
    String346& concat(const String346 &catString);

    //...
};

String346::String346() : data(NULL), size(0) {
}

String346::String346(const char * oldString) : data(NULL), size(std::strlen(oldString)) {
    data = new char[size+1];
    std::copy_n(oldString, size, data);
    data[size] = 0;
}

String346::String346(const String346 &oldString) : data(NULL), size(oldString.size) {
    data = new char[size+1];
    std::copy_n(oldString.data, size, data);
    data[size] = 0;
}

String346::~String346() {
    delete[] data;
}

String346& operator=(const char *newString) {
    String346 tmp(newString);
    std::swap(data, tmp.data);
    size = tmp.size;
    return *this;
}

String346& operator=(const String346 &newString) {
    String346 tmp(newString);
    std::swap(data, tmp.data);
    size = tmp.size;
    return *this;
}

String346 & String346::concat(const char *catString) {
    unsigned int catSize = std::strlen(catString);
    String tmp;
    tmp.size = size + catSize;
    tmp.data = new char[tmp.size+1];
    std::copy_n(data, size, tmp.data);
    std::copy_n(catString, catSize, tmp.data+size);
    tmp.data[tmp.size] = 0;
    std::swap(data, tmp.data);
    size = tmp.size;
    return *this;
}

String346 & String346::concat(const String346 & catString) {
    String tmp;
    tmp.size = size + catString.size;
    tmp.data = new char[tmp.size+1];
    std::copy_n(data, size, tmp.data);
    std::copy_n(catString.data, catString.size, tmp.data+size);
    tmp.data[tmp.size] = 0;
    std::swap(data, tmp.data);
    size = tmp.size;
    return *this;
}

关于c++ - 通过引用返回/传递动态分配的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36143579/

相关文章:

c++ - 'volatile' 是否足以阻止 C++ 编译器优化静默写入?

c++ - 密码无法正确加密(携带太多字符)

c++ - 在 g++ 的 `= 0' token 错误之前无效的纯说明符(仅允许 ‘;’)

C++ : Modifying a timer

c++ - 通过引用返回对象

vb.net - VB.NET,对象是通过函数引用返回的

c++ - 使用 boost::mpl::lambda 从基于静态常量成员变量的 boost::mpl::list 中删除类型

C++:如何制作作为引用返回的 char 的拷贝?

c++ - 为什么我们可以返回对类成员变量的引用

c++ - 为什么对常量临时值的本地引用似乎比定义它的方法生命周期更长?