相关疑难解决方法(0)

使用右值参考成员?

我想知道一个右值引用成员有什么用

class A {
  // ...
  // Is this one useful?
  Foo &&f;
};
Run Code Online (Sandbox Code Playgroud)

与左值参考成员相比,它有任何好处或缺点吗?什么是它的主要用途?

c++ rvalue-reference c++11

39
推荐指数
2
解决办法
5054
查看次数

表达式模板和C++ 11

让我们看一下表达式模板的一个特殊优点:ET可用于避免在重载运算符中出现的内存中的矢量大小临时值,如:

template<typename T>
std::vector<T> operator+(const std::vector<T>& a, const std::vector<T>& b)
{
  std::vector<T> tmp;   // vector-sized temporary
  for_each(...);
  return tmp;
}
Run Code Online (Sandbox Code Playgroud)

在C++ 11中,此函数的return语句应用移动语义.没有矢量的副本.这是一场胜利.

但是,如果我看一个像这样的简单表达式

d = a + b + c;
Run Code Online (Sandbox Code Playgroud)

我看到上面的函数被调用两次(两者都有operator+),而最后的赋值可以用移动语义来完成.

总共执行2个循环.意思是我把一个临时的,然后读回来.对于大向量,这不属于缓存.这比表达模板更糟糕.他们可以在一个循环中完成整个过程.ET可以执行上述代码,相当于:

for(int i=0 ; i < vec_length ; ++i)
  d[i] = a[i] + b[i] + c[i];
Run Code Online (Sandbox Code Playgroud)

我想知道lambdas与移动语义或任何其他新功能一起是否可以像ET一样好.有什么想法吗?

编辑:

基本上,使用ET技术,编译器构建一个解析树,类似于代数表达式和它的类型系统.该树由内部节点和叶子节点组成.内部节点表示操作(加法,乘法等),叶节点表示对数据对象的引用.

我尝试以堆栈计算机的方式考虑整个计算过程:从操作堆栈中获取操作并从参数堆栈中提取下一个参数并评估操作.将结果放回堆栈等待操作.

为了表示这两个不同的对象(操作堆栈和数据叶堆栈),我将一个捆绑在一起std::tuple用于操作,一个 捆绑在一起std::tuple用于数据std::pair<>.最初我使用了a std:vector但导致了运行时开销.

整个过程分为两个阶段:堆栈机器初始化,其中初始化操作和参数堆栈.以及通过将配对的容器分配给向量来触发的评估阶段.

我创建了一个Vec包含私有array<int,5>(有效负载)的类,它具有一个带有"表达式"的重载赋值运算符.

operator*对于所有拍摄Vec和"表达"的组合,全局都会超负荷, 以便在我们不仅仅是的情况下也能正确处理a*b.(注意,我将这个教育示例转换为乘法 - 基本上是为了快速发现imull汇编程序.) …

c++ expression-templates c++11

34
推荐指数
2
解决办法
1万
查看次数

使用vector :: push_back移动

假设我有以下代码:

#include <vector>
struct A {
    int a;
    int x;
};
int main() {
    using namespace std;
    A a1;
    A a2;
    vector<A> va;
    va.push_back(a1);
    va.push_back(move(a2));
}
Run Code Online (Sandbox Code Playgroud)

我知道std :: vector的元素是连续存储的,与std :: list不同.在上面的代码a2被移动但是真的没有复制a2到向量vava.push_back(a2);和之间有什么区别va.push_back(move(a2));

c++ c++11

33
推荐指数
2
解决办法
3万
查看次数

何时应该在字符数组上使用std :: string?

当我设计类接口时,我坐在那里思考是否应该使用const char*const std::string&经常使用它,当它归结为它时,我常常觉得一只手中有6只,另一只手拿着半打.

采用以下两个函数原型:

void foo(const char* str);
void foo(std::string str);
Run Code Online (Sandbox Code Playgroud)

如果foo函数是存储字符串,我会说第二个是更好的选择,因为能够传递字符串并尽可能利用移动语义.但是,如果foo只需要读取字符串,const char*解决方案会更好吗?

从性能角度来看,std::string不需要创建临时的.但是,使用已经存在的字符串作为参数调用该函数看起来很突出:foo(mystr.c_str()).更糟糕的是,如果需要在未来的某个时刻对阵列进行更高级的操作,或者如果应该存储副本,则接口必须进行更改.

所以我的问题是:

是否有明确的定义,无论是个人的还是其他的,约定何时std::string或是const char*更好的选择?此外,在开始一个新项目时,最好是与使用保持一致,还是只考虑最适合当前代码块的哪一个?

c++ string character-arrays

33
推荐指数
3
解决办法
3411
查看次数

如果我们已经拥有RVO,那么移动语义会提供什么优化?

据我所知,添加移动语义的目的之一是通过调用特殊构造函数来复制"临时"对象来优化代码.例如,在这个答案中我们看到它可以用来优化这些string a = x + y东西.因为x + y是一个rvalue表达式,所以我们只能复制指向字符串的指针和字符串的大小,而不是深度复制.但正如我们所知,现代编译器支持返回值优化,因此不使用移动语义,我们的代码根本不会调用复制构造函数.

为了证明这一点,我写了这段代码:

#include <iostream>

struct stuff
{
        int x;
        stuff(int x_):x(x_){}
        stuff(const stuff & g):x(g.x)
        {
                std::cout<<"copy"<<std::endl;
        }
};   
stuff operator+(const stuff& lhs,const stuff& rhs)
{
        stuff g(lhs.x+rhs.x);
        return g;
}
int main()
{
        stuff a(5),b(7);
        stuff c = a+b;
}
Run Code Online (Sandbox Code Playgroud)

在VC++ 2010中执行它并在优化模式下执行g ++后,我得到空输出.

它是什么样的优化,如果没有它,我的代码仍然可以更快地运行?你能解释一下我的理解错误吗?

c++ optimization move-semantics c++11

32
推荐指数
3
解决办法
5285
查看次数

在什么情况下调用C++拷贝构造函数?

我知道c ++中的以下情况,其中将调用复制构造函数:

  1. 当为现有对象分配其自己的类的对象时

    MyClass A,B;
    A = new MyClass();
    B=A; //copy constructor called 
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果函数接收作为参数,按值传递,则为类的对象

    void foo(MyClass a);
    foo(a); //copy constructor invoked
    
    Run Code Online (Sandbox Code Playgroud)
  3. 当函数返回(按值)类的对象时

    MyClass foo ()
       {
          MyClass temp;
          ....
          return temp; //copy constructor called
       } 
    
    Run Code Online (Sandbox Code Playgroud)

请随时纠正我所犯的任何错误; 但是如果有任何其他情况需要调用复制构造函数,我会更好奇.

c++ constructor copy-constructor visual-c++

30
推荐指数
5
解决办法
3万
查看次数

内置类型有移动语义吗?

考虑以下代码:

#include <iostream>
using namespace std;

void Func(int&& i) {
    ++i;
}

int main() {
    int num = 1234;
    cout << "Before: " << num << endl;
    Func(std::move(num));
    cout << "After: " << num << endl;
}
Run Code Online (Sandbox Code Playgroud)

它的输出是:

Before: 1234
After: 1235
Run Code Online (Sandbox Code Playgroud)

显然,i正在内部进行修改Func,因为它i在被"转换"为r值引用之后被绑定到参数std::move.

好吧,我的观点:

移动对象意味着将资源的所有权从一个对象转移到另一个对象.但是,内置类型不包含资源,因为它们本身就是资源.转移他们持有的资源毫无意义.如示例所示,num修改了s值.它的资源,它的自我,是被修改的资源.

内置类型有移动语义吗?

另外,内置类型对象在移动后(如果是)是一个明确定义的行为吗?

c++ built-in-types move-semantics c++11

25
推荐指数
1
解决办法
5227
查看次数

究竟什么是C++中的R值?

有人可以向R-Value解释或指出某种解释吗?我不确定它是什么,我的项目必须加入它.下面是R-Value的演示(第一部分是r_string.hpp):

#include <algorithm>
#include <iostream>

template <typename CHAR_T = char>

class basic_rstring {
public:
    typedef CHAR_T  value_type;
    typedef CHAR_T* pointer_type;
    typedef CHAR_T const*   pointer_const_type;
private:
    pointer_type    _data;
    std::size_t     _length;
public:
    basic_rstring() : _data(nullptr), _length(0) 
    {
        std::cout << "Default ctor\n";
    }

    basic_rstring( pointer_const_type s ) 
        : _data( nullptr )
        , _length( 0 )
    {
        std::cout << "Literal ctor: " << s << std::endl;
        _length = strlen( s );
        _data = new value_type[ _length + 1 ];
        std::copy( s, s + _length …
Run Code Online (Sandbox Code Playgroud)

c++ c++11

23
推荐指数
2
解决办法
2万
查看次数

何时调用Move Constructor?

我很困惑何时调用移动构造函数与复制构造函数.我已经阅读了以下资料:

移动构造函数未在C++ 0x中调用

在C++ 11中移动语义和右值引用

MSDN

所有这些来源要么过于复杂(我只想要一个简单的例子),要么只展示如何编写移动构造函数,而不是如何调用它.我写了一个简单的问题更具体:

const class noConstruct{}NoConstruct;
class a
{
private:
    int *Array;
public:
    a();
    a(noConstruct);
    a(const a&);
    a& operator=(const a&);
    a(a&&);
    a& operator=(a&&);
    ~a();
};

a::a()
{
    Array=new int[5]{1,2,3,4,5};
}
a::a(noConstruct Parameter)
{
    Array=nullptr;
}
a::a(const a& Old): Array(Old.Array)
{

}
a& a::operator=(const a&Old)
{
    delete[] Array;
    Array=new int[5];
    for (int i=0;i!=5;i++)
    {
        Array[i]=Old.Array[i];
    }
    return *this;
}
a::a(a&&Old)
{
    Array=Old.Array;
    Old.Array=nullptr;
}
a& a::operator=(a&&Old)
{
    Array=Old.Array;
    Old.Array=nullptr;
    return *this;
}
a::~a()
{
    delete[] Array;
} …
Run Code Online (Sandbox Code Playgroud)

c++ move-constructor c++11

23
推荐指数
2
解决办法
2万
查看次数

C++将简单值转换为字符串

现在我用下面的一段代码dummily转换基本类型(int,long,char[],这种东西),以std::string进行进一步的处理:

template<class T>
constexpr std::string stringify(const T& t)
{
    std::stringstream ss;
    ss << t;
    return ss.str();
}
Run Code Online (Sandbox Code Playgroud)

但是我不喜欢它依赖的事实std::stringstream.我尝试使用std::to_string(来自C++ 11的保留节目)然而它会扼杀char[]变量.

有一种简单的方法可以为这个问题提供优雅的解决方案吗?

c++ stringstream string-conversion c++11

22
推荐指数
4
解决办法
4864
查看次数