C ++构造函数 - 通过引用传递仅适用于const。为什么呢?

时间:2015-11-09 13:05:41

标签: c++ c++11 parameter-passing pass-by-reference pass-by-value

今天早些时候,我正在追赶好的旧C ++,当我编写代码时,它无法正常工作。像一些程序员一样,我开始讨厌,并最终发现添加键盘const解决了这个问题。但是,我不喜欢黑客攻击很多,并希望在添加const后找出代码工作正常的原因。

这是我的代码之前将const添加到构造函数中:

#include <iostream>
#include <string>

using namespace std;

class Names {
private:
    string _name;
    string _surname;

public:
    Names(string &name, string &surname) : _name(name), _surname(surname) {}

    string getName() const {return _name;}
    string getSurname() const {return _surname;}
};

int main(){
    Names names("Mike", "Man");

    cout << names.getName() << endl;
    cout << names.getSurname() << endl;
}

我收到了这些错误:

names.cc:19:27: error: no matching function for call to ‘Names::Names(const char [5], const char [4])’
  Names names("Mike", "Man");
                           ^
names.cc:19:27: note: candidates are:
names.cc:11:2: note: Names::Names(std::string&, std::string&)
  Names(string &name, string &surname) : _name(name), _surname(surname) {}
  ^
names.cc:11:2: note:   no known conversion for argument 1 from ‘const char [5]’ to ‘std::string& {aka std::basic_string<char>&}’
names.cc:5:7: note: Names::Names(const Names&)
 class Names {
       ^
names.cc:5:7: note:   candidate expects 1 argument, 2 provided
<builtin>: recipe for target 'names' failed
make: *** [names] Error 1

但是,在构造函数const中添加Names(string const &name, string const &surname) : _name(name), _surname(surname) {}关键字后,它似乎正在运行。

这是我的工作代码:

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

class Names {
private:
    string _name;
    string _surname;

public:
    Names(string const &name, string const &surname) : _name(name), _surname(surname) {}

    string getName() const {return _name;}
    string getSurname() const {return _surname;}

};

int main(){
    Names names("Mike", "Man");
    cout << names.getName() << endl;
    cout << names.getSurname() << endl;
}

现在,有几个问题:

  1. 如果没有const传递代码,为什么代码无效 参考?总是通过引用传递给你的好习惯 构造函数,如果是这样,那就意味着我们必须使用const 关键词?
  2. 所以如果我在构造函数中通过值传递说: Names(string name, string surname) : _name(name), _surname(surname) {}这是否意味着_name_surname为空或是他们  传递的价值。我知道传递值,变量的副本  正在制作并正在对副本进行更改。但是什么时候  副本会被毁坏还是超出范围?这有点令人困惑。
  3. 由于

3 个答案:

答案 0 :(得分:13)

string literal必须转换为std::string,这是一个临时的,而你cannot pass a temporary by non-const reference

答案 1 :(得分:2)

向@ CoryKramer的解释添加内容非常困难

  

必须将字符串文字转换为std :: string   一个临时的,你不能通过非const引用传递一个临时的。

这不仅仅是改写它。

无论如何,这是你(@ CodeMan)可以使用

的一些检测代码
#include <iostream>

std::ostream& logger = std::clog;

struct A {
    A() = delete;
    A(int ii) : i(ii) {logger << "A(int) ctor\n";}
    A(const A& a) : i(a.i) {logger << "A copy ctor\n";}
    A& operator= (const A& a) { i = a.i; logger << "A copy assigment\n"; return *this;};
    // nothing to steal here
    A(A&& a) : i(a.i) {logger << "A move ctor\n";}
    A& operator= (A&& a) {i = a.i; logger << "A move assigment\n"; return *this;};
    ~A() {logger << "A dtor\n";}

    int i;
};

void foobar(const A& a) {
    logger << "foobaring const A&\n";
}

void foobar(A& a) {
    logger << "foobaring A&\n";
}


int main(){
  int i(42);  
  A a(i);
  logger << "ctored a\n===================\n";  
  foobar(a);
  logger << "foobared a\n-------------------\n";  
  foobar(i);
  logger << "foobared " << i << "\n===================" << std::endl;
}

live在Coliru's。

从输出中可以看出

[...]
===================
foobaring A&
foobared a
-------------------
A(int) ctor
foobaring const A&
A dtor
foobared 42
===================
[...]

在第二个foobar调用中隐含地从该int参数中获取临时A,并将该临时A实例传递给另一个,即{{1的const版本因此,foobar

而且你也可以在第二次const A &返回之后,暂时foobar被删除。

答案 2 :(得分:0)

1-“Mike”和“Man”在你对构造函数的调用中是临时的,非const引用不能绑定到temporaries。 按值传递内置类型更有效,所有其他对象通过 const 引用。

2-如果您通过值_name传递,_surname将传递值。传递的参数副本对于函数是本地的,因此当构造函数超出范围时它们会被销毁。