相关疑难解决方法(0)

由于右值引用,在C++ 0x中是std :: swap atomic吗?

由于我们在C++ 0x中有rvalue引用,在我看来应该可以将std :: swap实现为CAS的原子操作.这是新标准的情况,如果不是为什么?

c++ c++11

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

从std :: tuple解压缩的值的返回值优化

是否有任何编译器能够通过std :: tuple对函数返回的多个值进行返回值优化?需要说明的是,在下面的代码中,是否有任何编译器能够避免不必要的副本?

std::vector<int> a;
std::list<float> b;
std::tie(a,b) = myFunctionThatReturnsAVectorAndList();
Run Code Online (Sandbox Code Playgroud)

c++ tuples return-value-optimization c++11

7
推荐指数
1
解决办法
476
查看次数

移动语义和const引用

我花了很多时间为我的类实现移动语义,但现在我正在处理使用它的函数.

好的,所以我有这个对象,它在堆上有很多数据:CLargeOb为此我实现了移动语义(constructor和operator =).它理想地使用如下:

void OtherOb::Func(CLargeOb&& largeOb1, CLargeOb&& largeOb2)
{
    SomeOtherFunc(largeOb1); // use objects
    SomeOtherFunc(largeOb2); 
    m_largeOb1 = (CLargeOb&&)largeOb1; // save as members and trash the originals
    m_largeOb2 = (CLargeOb&&)largeOb2;
}
Run Code Online (Sandbox Code Playgroud)

然而,并不总是允许移动/删除对象,所以我添加了这两个函数:

void OtherOb::Func(const CLargeOb& largeOb1, CLargeOb&& largeOb2)
{
    SomeOtherFunc(largeOb1);
    SomeOtherFunc(largeOb2); 
    m_largeOb1 = largeOb1;
    m_largeOb2 = (CLargeOb&&)largeOb2;
}

void OtherOb::Func(CLargeOb&& largeOb1, const CLargeOb& largeOb2)
{
    SomeOtherFunc(largeOb1);
    SomeOtherFunc(largeOb2); 
    m_largeOb1 = (CLargeOb&&)largeOb1;
    m_largeOb2 = largeOb2;
}
Run Code Online (Sandbox Code Playgroud)

虽然它有效但是你已经可以猜到当我有一个将这些对象中的3个或更多作为参数的函数时,它将成为*ss中的一个主要痛苦...是不是有一种聪明的方法来解决这个使用模板或者也许'完美转发'?

c++ c++11

7
推荐指数
1
解决办法
1721
查看次数

是否不可能在没有指针的循环中构造实例?

这段代码会爆炸,对吗?一旦循环退出,原始实例将与其所有内部成员一起死亡,因此如果它们不是POD,那么任何do_stuff需要访问成员的方法B都会抛出分段错误,对吗?

void foo() {
  std::vector<B> bar;
  for (int i = 0; i < 7; i++)
    bar.push_back(B(i, i, i));
  bar[3].do_stuff();
}
Run Code Online (Sandbox Code Playgroud)

那么,有没有办法在不使用指针的情况下做到这一点?或者你必须这样做:

void foo() {
  std::vector<B*> bar;
  for (int i = 0; i < 7; i++)
    bar.push_back(new B(i, i, i));
  bar[3]->do_stuff();
  for (int i = 0; i < 7; i++)
    delete bar[i];
}
Run Code Online (Sandbox Code Playgroud)

c++

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

什么是语义?

所以有复制语义,移动语义和更多我不知道的语义.我读过关于这两者的文章,但我仍然没有真正对"语义"有一个很好的定义.顾名思义,移动语义与移动事物有关,但为什么它被称为移动语义

更清晰的版本:编程语境中语义的含义是什么?示例:移动和复制语义.

c++

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

xvalues 与 prvalues:身份属性添加了什么

我对这个问题的广泛性感到抱歉,只是所有这些细节都是紧密相连的。

我一直在尝试理解两个特定值类别 - xvalues 和 prvalues 之间的区别,但我仍然感到困惑。

不管怎样,我试图为自己开发的“同一性”概念的心智模型是,应该保证具有同一性的表达式驻留在实际程序的数据存储器中。

由于这个原因,字符串文字是左值,它们保证在整个程序运行期间驻留在内存中,而数字文字是纯右值,并且可以假设存储在直接汇编中。

这似乎同样适用于std::move纯纯右值文字,即,在调用时,fun(1)我们只会在被调用者框架中获得参数左值,但在调用时,fun(std::move(1))左值的 xvalue“种类”必须保留在调用者框架中。

然而,这种心理模型至少不适用于临时对象,据我所知,临时对象应该始终在实际内存中创建(例如,如果像使用纯右值参数那样调用fun(MyClass())右值引用函数)。所以我认为这种思维模式是错误的。

那么,思考 xvalue 的“同一性”属性的正确方法是什么?我已经读过,通过身份我可以比较地址,但是如果我可以比较 2 的地址MyClass().member(根据 cppreference 的 xvalue),比方说通过右值引用将它们传递到某个比较函数中,那么我不明白为什么我可以不对 2 MyClass()s(纯右值)做同样的事情吗?

与此相关的另一个来源是此处的答案: 什么是移动语义?

请注意,尽管 std::move(a) 是右值,但其求值不会创建临时对象。这个难题迫使委员会引入第三个价值类别。可以绑定到右值引用的东西,即使它不是传统意义上的右值,也称为xvalue(到期值)。

但这似乎与“可以比较地址”无关,并且a)我不明白这与右值的“传统意义上”有什么不同;b) 我不明白为什么这样的原因需要语言中的新值类别(好吧,这允许为 OO 意义上的对象提供动态类型,但 xvalue 不仅仅指对象)。

c++ xvalue c++14 prvalue value-categories

7
推荐指数
1
解决办法
800
查看次数

结构初始化中的const正确性

我现在正在玩C++和const-correctness.假设您具有以下结构

template <typename T>
struct important_structure {
    public:
    T* data;
    int a;
    important_structure(const T& el, int a);
    void change();
};

template <typename T>
void important_structure<T>::change() {
    //alter data field in some way
}

template <typename T>
important_structure <T>::important_structure(const T& el, int a) : data(&el), a(a) //error line {
};


int main() {
    important_structure<int>* s = new important_structure<int>{5, 3};
}
Run Code Online (Sandbox Code Playgroud)

编译时std=c++11,编译器返回以下错误:

从'const int*'到'int*'的无效转换

现在,我知道这是不安全投下const int*int*.问题是我有一个数据结构,我不想把字段data作为常量.

但是,我不想删除const构造函数中的限定符,因为我认为它为未来的开发人员提供了信息:它明确表示el不会被函数修改.仍然data可以通过其中的一些其他功能来修改该字段important_structure …

c++ const-correctness

7
推荐指数
1
解决办法
350
查看次数

std::move 与复制省略

以下代码在 Visual Studio 2019 msvc x64 中编译时不会出现警告:

class ThreadRunner {
public:
    void start() {
        m_thread = std::move(std::thread(&ThreadRunner::runInThread, this));
    }
    
private:
    void runInThread() {
        for (int i = 0; i < 1000 * 1000; i++) {
            std::cout << "i: " << i << "\n";
        }
    };
    std::thread m_thread;
};
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用 x64-Clang 编译相同的代码,我会收到以下警告:

warning : moving a temporary object prevents copy elision [-Wpessimizing-move]
Run Code Online (Sandbox Code Playgroud)

这是否意味着我应该写:

m_thread = std::thread(&ThreadRunner::runInThread, this);
Run Code Online (Sandbox Code Playgroud)

反而?编译器会优化掉(“复制删除”)临时变量吗?

msvc x64也会复制删除临时变量吗?

我做了一个实验:

struct B {
    void f1() {
        a = A(5);
    } …
Run Code Online (Sandbox Code Playgroud)

c++ visual-studio

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

C++ 11/VS2010:返回不可复制但可移动的对象的容器

请考虑以下代码:

#include <vector>
#include <boost/noncopyable.hpp>

struct A : private boost::noncopyable
{
  A(int num, const std::string& name)
    : num(num),
      name(name)
  {
  }

  A(A&& other)
    : num(other.num),
      name(std::move(other.name))
  {
  }

  int num;
  std::string name;
};

std::vector<A> getVec()
{
  std::vector<A> vec;
  vec.emplace_back(A(3, "foo"));
  // vec.emplace_back(3, "foo"); not available yet in VS10?

  return vec; // error, copy ctor inaccessible
}

int main ( int argc, char* argv[] )
{
  // should call std::vector::vector(std::vector&& other)
  std::vector<A> vec = getVec();

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

这并不在VS2010编译,因为很明显A是 …

c++ visual-studio-2010 visual-c++ move-semantics c++11

6
推荐指数
2
解决办法
1211
查看次数

移动构造函数没有指针

我知道这个问题可能看起来非常基本.但我无法找到任何一个没有指针的移动构造函数的例子.

我有一个包含矢量对象变量的类.不是一个指针.所以我的问题:这是否意味着我不需要移动构造函数?或者我的实现是错误的,我应该使用指向向量的指针,然后使用移动构造函数?

谢谢

c++ c++11

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