如何使用Strings作为参数初始化构造函数?

时间:2013-11-05 23:11:16

标签: c++ string constructor

我不确定我是否使用了正确的术语,但问题是如何正确地构造一个将字符串作为参数的构造函数?

我习惯在构造函数中使用const char *而不是字符串。

通常我会做这样的事情:

Name(const char* fName, const char* lName)
    : firstName(0), lastName(0)
{
    char * temp = new char [strlen(fName) + 1];
    strcpy_s(temp, strlen(fName) + 1, fName);
    firstName = temp;

    char * temp2 = new char [strlen(lName) + 1];
    strcpy_s(temp2, strlen(lName) + 1, lName);
    lastName = temp2;
}

如果构造函数是这样的:

 Name(const string fName, const string lName) { }

我还在做基本会员初始化吗?我还需要在构造函数的基础上使用字符串副本吗?

4 个答案:

答案 0 :(得分:11)

使用std::string和初始化列表:

std::string fName, lName;

Name(string fName, string lName):fName(std::move(fName)), lName(std::move(lName))
{
}

在这种情况下,您不需要使用非常简单的指针,您不需要分配内存,复制字符并最终解除分配。此外,由于std::string是可移动的,因此这个新代码有机会利用移动而不是复制。阅读this也很有用。

依旧......

答案 1 :(得分:9)

我看到你已经接受了答案,但我想扩大答案。

正如deepmax所说,如果你通过值传递,你可以编写你的构造函数来利用"移动语义"。这意味着它不是复制数据,而是可以从一个变量移动到另一个变量。

这样写:

class Name{
    public:
        Name(std::string var): mem_var(std::move(var)){}

        std::string mem_var;
};

这似乎是一个好主意,但实际上并不比复制构造函数

更有效
class Name{
    public:
        Name(const std::string &var): mem_var(var){}

        std::string mem_var;
};

这是因为在一般用例中看起来像这样:

auto main() -> int{
    Name name("Sample Text");
}

任何一种方式都只能制作一份副本(见copy elision),而另一种方式

auto main() -> int{
    std::string myname = "Hugh Jaynus";
    Name name(myname);
}

将在'高效'中制作2份副本。按值传递移动语义方式!

这是一个很好的例子,说明复制构造函数(或通过引用传递)应该,而不是反对它的示例。

恰恰相反......

如果编写一个使用移动语义的显式构造函数,无论在什么情况下都可以得到有效的解决方案。

以下是 I 将如何写出类定义:

class Name{
    public:
        Name(const std::string &first_, const std::string &last_)
            : first(first_), last(last_){}

        Name(std::string &&first_, std::string &&last_) // rvalue reference
            : first(std::move(first_)), last(std::move(last_)){}

        std::string first, last;
};

然后当你使用这个类时,可以决定何时更有效。

如果我们回到我们的例子,我们可以重写它们以使用最好或最有效的构造函数:

auto main() -> int{
    // pass by reference best here
    Name myname("Yolo", "Swaggins");

    // move most efficient here
    // but never use 'first' and 'last' again or UB!
    std::string first = "Hugh", last = "Jaynus";
    Name yourname(std::move(first), std::move(last));
}

永远不要理所当然地认为一种解决方案比其他解决方案更好!

答案 2 :(得分:3)

我习惯这样做:

std::string fName;
std::string lName;

Name(const std::string &fName, const std::string &lName) :
     fName(fName), lName(lName)
{
}

使用引用可以节省将字符串复制到堆栈上的新对象的工作,它只会将引用传递给现有字符串。一旦将它们分配给班级成员,他们就会被复制。

答案 3 :(得分:0)

如果你想保持const char *作为你的构造函数输入类型。

std::string fName;
std::string lName;

Name(const char *_fName, const char *_lName) :
     fName(_fName), lName(_lName)
{
}

您可以从const char构建一个std :: string。