2

我有一个对象,它的复制操作太慢了,所以我决定这样delete做并强制用户只移动。无论如何,这个对象伤口的副本没有多大意义。但后来我有这个功能:

Object loadFromFile(const std::string& name) {
    Object obj;
    ...
    return obj;
}

即使这里发生了复制省略并且没有调用复制构造函数,这也无法编译,因为需要复制构造函数存在并且可以访问。这是我的第二次尝试:

Object&& loadFromFile(const std::string& name) {
    Object obj;
    ...
    return std::move(obj);
}

这编译。耶!

但是在尝试使用它时又出现了一个新问题:

Object x = loadFromFile("test.txt");

这又需要一个复制构造函数。即使明确使用move,我也无法让它工作:

Object x = std::move(loadFromFile("test.txt"));

我来的唯一解决方案是:

const Object& x = loadFromFile("test.txt");

x必须是非常量的,因为它稍后会被改变。

如何处理?

4

3 回答 3

3

这个是错的:

Object&& loadFromFile(const std::string& name) {
    Object obj;
    ...
    return std::move(obj);
}

您正在返回对局部变量的引用,这是未定义的行为。对象死了,你返回的是对你鼻子的引用,所以恶魔可以从中出来。

第二个是对的:

Object loadFromFile(const std::string& name) {
    Object obj;
    ...
    return obj;
}

实际上,在这种情况下,首先执行查找,就好像它obj是一个右值(标准 12.8.32):

当满足复制/移动操作的省略条件,但不满足异常声明,并且要复制的对象由左值指定时,或者当返回语句中的表达式是(可能带括号的)id-使用在最内层封闭函数或 lambda 表达式的主体或参数声明子句中声明的自动存储持续时间命名对象的表达式,首先执行为复制选择构造函数的重载决策,就好像对象由右值指定一样. 如果第一个重载决议失败或未执行,或者如果所选构造函数的第一个参数的类型不是对对象类型的右值引用(可能是 cv 限定的),则再次执行重载决议,将对象视为左值。[注意:无论是否会发生复制省略,都必须执行此两阶段重载解析。它确定在不执行省略时要调用的构造函数,并且即使调用被省略,所选构造函数也必须是可访问的。——尾注]

Object(Object&&)并且应该选择移动构造函数。

于 2015-02-25T12:39:54.327 回答
2

操作,我的错误,对不起。

我删除了复制构造函数,但实际上并没有实现一个移动,假设它已经存在。创建一个移动构造函数可以解决这个问题。

感谢@Joseph Mansfield 的光。

于 2015-02-25T12:11:42.023 回答
0

您可以将其作为输出参数传递吗?就像是:

void loadFromFile(const std::string& name, Object& obj) {
    //Operations on obj
}
于 2015-02-25T12:07:38.173 回答