C++ 如何同时使用变量和移动变量?

C++ 如何同时使用变量和移动变量?,c++,constructor,c++17,move,order-of-execution,C++,Constructor,C++17,Move,Order Of Execution,假设我们有以下代码: struct some_class : parent { some_class(::other_class oth) : parent(some_function(oth.some_property), std::move(oth)) {} }; 当然,在未定义的行为中,构造结果(在我的例子中崩溃),因为C++没有指定执行顺序。但是,我怎样才能在搬家前收回财产呢?我无法更改父级。创建一个辅助函数来构造父级,您可以在其中添加排序: pare

假设我们有以下代码:

struct some_class : parent
{

    some_class(::other_class oth) :
       parent(some_function(oth.some_property), std::move(oth))
    {}

};

当然,在未定义的行为中,构造结果(在我的例子中崩溃),因为C++没有指定执行顺序。但是,我怎样才能在搬家前收回财产呢?我无法更改父级。

创建一个辅助函数来构造父级,您可以在其中添加排序:

parent make_parent(::other_class &&oth) {
    auto sf = some_function(oth.some_property);
    return parent(sf, std::move(oth));
}

some_class(::other_class oth) :
    parent(make_parent(std::move(oth))
{}

正如您所注意到的,该问题是由于未指定的执行顺序造成的。 通过使
parent
通过右值引用而不是左值获取对象,可以消除未定义的行为。这样,它就得到了对现有对象的引用,而该对象在内存中的数据实际上不会被移动。即:

struct parent {
   parent (int thing, SomeProperty && some_property) { /* Do stuff. */ }
};
在这种情况下,在
oth
上执行
std::move
并不重要。它的数据实际上不会移动到另一个对象中,因为
parent
需要一个右值引用。因此,即使首先调用了
std::move
,您的
某个函数(我假设它通过const-lvalue引用获取
oth
)也会有一个合适的对象来处理

这里的主要缺点是父级现在总是需要in-rvalue。因此,如果不移动它,就不能将其作为对象传递。这意味着,如果你有一个不想丢弃的对象,你首先必须显式地复制它。即:

other_class wantToKeepThis;
auto foo = parent(wantToKeepThis); // Doesn't compile.
auto foo = parent(std::move(wantToKeepThis)); // Object gone, don't want this.
auto foo = parent(other_class(wantToKeepThis)); // OK, copied, parent gets rvalue.

您可以尝试委托构造函数:

struct some_class : parent
{

    some_class(::other_class oth) :
       some_class(some_function(oth.some_property), std::move(oth))
    {}

private:
    some_class(const ::Foo& foo, ::other_class&& oth) :
       parent(foo, std::move(oth))
    {}
};

你甚至可以用lambda来写,我想lambda在这种情况下看起来会非常模糊。此外,您需要在代码中留出一些空间,以便对此处发生的情况进行注释。几乎可以正常工作,但如果构造函数受到保护,并且类可能不可复制或移动呢?嗯。如果我将您的答案与Darhuuk的答案合并,我将获得某个类的委托构造函数(const::Foo&Foo,::other\u class&&oth),哪一个可能是我寻求的答案?如果直接调用第二个构造函数,我会发现这会导致非常意外的行为。我会让它成为一个私有构造函数。我以为你不能修改
parent
?@Dekakaruk如果你建议的编辑无法编译,那么委托构造函数会对reason@AlanBirtles我的错误,修正了。这里没有未定义的行为<代码>标准::移动
只是对右值引用的转换。罪魁祸首是
parent
的构造函数中的代码。因为没有显示,所以很难知道什么可能起作用。没错,不是真的没有定义,但绝对出乎意料。根据您使用的编译器的不同,
对“原始”
oth
或“从”
oth
移动”调用某些函数。如果
其他属性
是例如
std::string
,则它包含其原始值或为空。
某些函数
如何处理其参数
std::move
本身实际上并没有做任何事情。@Darhuuk只有当父级的构造函数按值而不是按引用获取第二个参数时,才会出现这种情况。否则,在执行父级的构造函数之前,不会发生任何问题。@walnut-True,我假设是这样的。否则这个问题就没什么意义了。我不想改变父级,但是你的想法是使用&&和Alan Birtles的构造函数委托可能是答案。