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

Sar*_*rah 11 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;
}
Run Code Online (Sandbox Code Playgroud)

如果构造函数是这样的:

 Name(const string fName, const string lName) { }
Run Code Online (Sandbox Code Playgroud)

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

mas*_*oud 12

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

std::string fName, lName;

Name(string fName, string lName):fName(std::move(fName)), lName(std::move(lName))
{
}
Run Code Online (Sandbox Code Playgroud)

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

等等....


Cof*_*ode 11

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

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

写得像这样:

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

        std::string mem_var;
};
Run Code Online (Sandbox Code Playgroud)

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

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

        std::string mem_var;
};
Run Code Online (Sandbox Code Playgroud)

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

auto main() -> int{
    Name name("Sample Text");
}
Run Code Online (Sandbox Code Playgroud)

只有一个副本可以用任何一种方式制作(参见copy elision),在另一种情况下

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

2个副本将以'高效'按值传递移动语义方式制作!

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


反之...

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

以下是将如何编写类定义:

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;
};
Run Code Online (Sandbox Code Playgroud)

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

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

int main(){
    // 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));
}
Run Code Online (Sandbox Code Playgroud)

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