相关疑难解决方法(0)

三元运算符?:vs if ... else

在C++中,?:运算符比if()... else语句更快?它们在编译代码中有什么区别吗?

c++ performance conditional-operator

69
推荐指数
4
解决办法
9万
查看次数

为什么三元运算符会阻止返回值优化?

为什么三元运算符会阻止MSVC中的返回值优化(RVO)?考虑以下完整的示例程序:

#include <iostream>

struct Example
{
    Example(int) {}
    Example(Example const &) { std::cout << "copy\n"; }
};

Example FunctionUsingIf(int i)
{
    if (i == 1)
        return Example(1);
    else
        return Example(2);
}

Example FunctionUsingTernaryOperator(int i)
{
    return (i == 1) ? Example(1) : Example(2);
}

int main()
{
    std::cout << "using if:\n";
    Example obj1 = FunctionUsingIf(0);
    std::cout << "using ternary operator:\n";
    Example obj2 = FunctionUsingTernaryOperator(0);
}
Run Code Online (Sandbox Code Playgroud)

使用VC 2013编译如下: cl /nologo /EHsc /Za /W4 /O2 stackoverflow.cpp

输出:

using if:
using ternary operator: …
Run Code Online (Sandbox Code Playgroud)

c++

11
推荐指数
1
解决办法
1138
查看次数

何时返回函数外部的值使用move vs copy?

看完这个问题后.我创建了这个小小的测试:

class A{
public:
    A(){}
    A(const A&){printf("copy\n");}
    A(A&&){printf("move\n");}

    static A f(){
        A a;
        return a;}

    static A g(){
        A a;
        return (a);}//could be return *&a; too.

    static A h(){
        A a;
        return true?a:a;}

 };
Run Code Online (Sandbox Code Playgroud)

结果是(没有RVO和NRVO):

  • f使用移动
  • g使用移动
  • h使用副本

据我所知,用于决定是否使用复制或移动的规则在12.8.32中描述:

  • 满足或将满足复制操作的省略标准时,除了源对象是函数参数这一事实,并且要复制的对象由左值指定,重载决策选择复制的构造函数是首先执行,好像对象是由右值指定的....

这是指12.8.31的规则:(我只显示相关部分)

  • 在具有类返回类型的函数的return语句中,当表达式是具有与函数返回类型相同的cvunqualified类型的非易失性自动对象(函数或catch子句参数除外)的名称时,副本通过将自动对象直接构造到函数的返回值中,可以省略/ move操作
  • 当一个未绑定到引用(12.2)的临时类对象被复制/移动到具有相同cv-nonqualified类型的类对象时,可以通过将临时对象直接构造到目标中来省略复制/移动操作省略的复制/移动

按照这些规则,我理解f和h会发生什么:

  • f中的副本有资格获得elision,因此被移动.(参见粗体部分)
  • h中的副本不符合elision的条件,因此会被复制.

怎么样?

对我来说,它看起来很像h.我正在返回一个表达式,它不是自动对象的名称,因此我认为它会被复制但是它被移动了.这里发生了什么?

c++ copy return move c++11

8
推荐指数
1
解决办法
446
查看次数

需要一些帮助才能理解C++ 11 Move Constructors

作为一个C++新手,我在理解C++ 11的新Move-Constructor时遇到了问题,我希望有人可以解释我偶然发现的具体情况.我们来看看这个示例代码:

#include <iostream>

using namespace std;

class Model {
public:
    int data;
    Model(int data) : data(data) { cout << "Constructor" << endl; }
    Model(Model&& model) { cout << "Move constructor" << endl; }
    ~Model() { cout << "Destructor" << endl; }

private:
    Model(const Model& model);
    const Model& operator=(const Model&);

};

Model createModel(int data) {
    return Model(data);
}

int main(void) {
    Model model = createModel(1);
    cout << model.data << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

所以我创建了一个createModel函数,它应该将模型作为临时右值返回,我想将它分配给左值.我不希望编译器创建Model对象的副本,因此我将复制构造函数定义为私有,并且我对赋值运算符执行相同操作以确保不复制任何数据.执行此操作后,代码正确不再编译,因此我添加了Move构造函数,现在它再次编译.但是当我运行程序时,我得到了这个输出:

Constructor
1 …
Run Code Online (Sandbox Code Playgroud)

c++ move-semantics c++11

8
推荐指数
1
解决办法
236
查看次数

我们可以在可能的情况下使用返回值优化,而不是复制,而不是复制,语义不是吗?

是否有可能在可能的情况下编写C++代码,我们依赖于返回值优化(RVO),但是否则可以依靠移动语义?例如,由于条件,以下代码无法使用RVO,因此它将结果复制回:

#include <iostream>

struct Foo {
    Foo() {
        std::cout << "constructor" << std::endl;
    }
    Foo(Foo && x) {
        std::cout << "move" << std::endl;
    }
    Foo(Foo const & x) {
        std::cout << "copy" << std::endl;
    }
    ~Foo() {
        std::cout << "destructor" << std::endl;
    }
};

Foo f(bool b) {
    Foo x;
    Foo y;
    return b ? x : y;  
}

int main() {
   Foo x(f(true));
   std::cout << "fin" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这产生了

constructor
constructor
copy
destructor
destructor
fin
destructor
Run Code Online (Sandbox Code Playgroud)

这是有道理的.现在,我可以通过更改行强制在上面的代码中调用移动构造函数

    return …
Run Code Online (Sandbox Code Playgroud)

c++ c++11 c++14

7
推荐指数
2
解决办法
592
查看次数

如何确保在不妨碍RVO的情况下移动?

从函数返回对象时,自C ++ 11起,可能会发生以下情况之一,假设已定义了移动构造函数和复制构造函数(另请参见本文结尾处的示例):

  1. 具有复制删除资格,并且编译器执行RVO。
  2. 它有资格进行复制删除,并且编译器不执行RVO,但是...
  3. 有资格使用move构造函数并被移动。
  4. 以上都不是,并且使用了复制构造函数。

前3种情况的建议不要使用显式std::move,因为无论如何执行移动都可能会阻止可能的RVO,例如参见此SO-post

但是,在4.情况下,显式std::move可以提高性能。但是,由于有些人既不懂标准又不懂汇编程序,所以需要花很多时间来区分情况1-3和4。

因此,我的问题有没有一种方法可以统一处理上述所有情况,例如:

  1. 不阻止RVO(情况1)
  2. 如果未执行RVO,则使用move-constructor(情况2、3和4)
  3. 如果没有移动构造函数,则应将复制构造函数用作后备。

这是一些示例,也可以用作测试用例。

所有示例都使用以下helper-class-definition:

struct A{
    int x;
    A(int x_);
    A(const A& a);
    A(A&& a);
    ~A();
};
Run Code Online (Sandbox Code Playgroud)

1.示例: 1.case,RVO执行,现场演示结果汇编程序

A callee1(){
    A a(0);
    return a;
}
Run Code Online (Sandbox Code Playgroud)

2.示例: 1.case,RVO执行,现场演示结果汇编程序

A callee2(bool which){
    return which? A(0) : A(1);
}
Run Code Online (Sandbox Code Playgroud)

3.示例: 2.case,有资格进行复制删除,未执行RVO,现场演示结果汇编程序

A callee3(bool which){ …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer rvo c++11

6
推荐指数
1
解决办法
190
查看次数

C++ 三元运算符调用复制构造函数而不是移动构造函数

我正在使用 VS Code 在 Linux 中使用 g++ 进行编译和调试。

需要包括和使用:

#include <string>
#include <iostream>

using namespace std;
Run Code Online (Sandbox Code Playgroud)

这是我的类是可移动的:

class A {
public:
    A(const string& strA) : strA(strA) {}

    A(const A& a) : A(a.strA) {
    }

    A(A&& a) : A(a.strA) {
        a.strA = "";
    }

    string strA;
};
Run Code Online (Sandbox Code Playgroud)

返回 A 实例的示例函数:

A RetA() {
    A a("a");
    A b("bha");

    string ex;
    cin >> ex;
    a.strA += ex;

    return ex == "123" ? a : b;
}
Run Code Online (Sandbox Code Playgroud)

这是简单的主要内容:

int main() {
    A a(RetA());

    return …
Run Code Online (Sandbox Code Playgroud)

c++ copy-constructor move-constructor

0
推荐指数
1
解决办法
67
查看次数