我在我的项目中有几个创建对象的函数.例如,如果你有一个函数来创建这样的对象:
int& f()
{
int *i = new int(5);
return *i;
}
Run Code Online (Sandbox Code Playgroud)
然后当你打电话给你时
int x = f();
Run Code Online (Sandbox Code Playgroud)
或类似的东西
std::cout << f();
Run Code Online (Sandbox Code Playgroud)
在函数中创建的int会发生什么?引用是像普通变量一样处理还是我做了一件非常错误的事情?如果是这样,制作物品的正确方法是什么?
我感到困惑的代码之后,我想不通为什么Test t作为参数calc,并return t会打电话Test(Test &t)?任何人都可以帮我说清楚吗?非常感谢!
#include <iostream>
using namespace std;
class Test {
public:
Test(int na, int nb) {
a = na;
b = nb;
}
Test(Test &t) {
a = t.a + 1;
b = t.b + 1;
}
int getValue() {
return a + b;
}
Test calc(Test t) {
return t;
}
private:
int a;
int b;
};
int main() {
Test t(1, 1);
cout << t.calc(t).getValue() << endl;
}
Run Code Online (Sandbox Code Playgroud) 我目前正在努力使用c ++和copy elision,特别是"命名返回值优化"(NRVO),以便能够实现工厂功能模式.我不能在不同的编译器中获得一致的行为.我的妈妈:
#include <iostream>
struct base {
virtual ~base() { std::cout << "dtor base\n"; }
};
struct derived : public base {
~derived() { std::cout << "dtor derived\n"; }
};
derived f() { return derived(); }
int main(int argc, char *argv[]) {
std::cout << "start\n";
new derived(f());
std::cout << "done. should have leaked!\n";
}
Run Code Online (Sandbox Code Playgroud)
注意:删除虚拟base-dtor可以解决问题,但我需要它才能实现真正的实现.
如果是gcc 5.4.0,则调用dtor,不执行复制省略:
$ g++ test2.cpp && ./a.out
start
dtor derived
dtor base
done. should have leaked!
Run Code Online (Sandbox Code Playgroud)
当使用gcc 5.4.1(Ubuntu称之为5.4.1,我认为这是svn-head)时,我可以接触到的所有clang以及各种其他gcc执行elision并成功泄漏内存:
$ g++ test2.cpp && …Run Code Online (Sandbox Code Playgroud) 我正在玩这个例子来理解右值引用:
#include <string>
#include <iostream>
#include <utility>
#include <vector>
class Dog
{
public:
Dog() {};
Dog(Dog&& a) { std::cout << "R value" << std::endl;}
};
Dog foo()
{
return Dog();
}
int main()
{
std::vector<Dog> v;
v.push_back(Dog()); // calls move constructor
Dog c((Dog())); // does not call move constructor
Dog d(foo()); // does not call move constructor
}
Run Code Online (Sandbox Code Playgroud)
我很难理解为什么在行v.push_back(Dog())中,对象Dog()被视为Rvalue(因此调用移动构造函数),但以下两行不会调用移动构造函数.我想我可能会误解匿名对象和RValue之间的关系.
编辑:它不是重复,因为这个问题询问编译器在O0中的决定.
据说这里是名称返回值优化(NRVO)是一个优化许多编译器的支持.但它是必须的还是只是一个很好的优化?
我的情况是,我想编译-O0(即没有优化),以方便调试,但我也希望NRVO启用返回对象(例如,向量)的返回语句.如果NRVO不是必须的,编译器可能不会在-O0模式下执行.在这种情况下,我应该更喜欢这个代码:
std::vector<int> foo() {
std::vector<int> v(100000,1); // an object that is really big..
return std::move(v); // explicitly move
}
Run Code Online (Sandbox Code Playgroud)
在这下面?
std::vector<int> foo() {
std::vector<int> v(100000,1);
return v; // copy or move?
}
Run Code Online (Sandbox Code Playgroud)
编辑:我使用的编译器是GCC6,但我希望代码与编译器无关.
假设我有一个带有 const int 成员变量的简单类:
class MyClass{
public:
Myclass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) :importantNumber{x}
{
this->anotherNumber = y;
}
Run Code Online (Sandbox Code Playgroud)
由于int importantNumberis const,我只能在构造函数创建对象期间设置它(使用成员初始化列表,如上所示)。
现在的问题是:在实际使用该值创建 importantNumber 之前,如何为构造函数的参数 x 添加验证?是否可以创建一个static int MyClass::validation(int a)并在构造函数的成员初始化列表上使用它,例如importantNumber{validation(x)}?
即使有可能,还有更好的方法吗?
在 java 中,可以使用return new int[] {1,2,3}. 在 C++ 中,我习惯先创建一个数组(比如 temp),然后将1,2,3其存储在其中,然后使用return temp. 我如何在{1,2,3}不使用 temp 的情况下返回。我可以在没有临时变量的情况下以类似的方式返回向量或映射(而不是数组)以将它们存储在 C++ 中吗?如果是,我该怎么做?
我在下面有这个私有成员函数,(类模板的一部分,Heap):
template <typename Task, typename Priority>
const size_t& Heap<Task, Priority>::parent_of(const size_t& index) const
{
// ** warning C4172: returning address of local variable or temporary
return (this_index-1)/2;
}
Run Code Online (Sandbox Code Playgroud)
我从其他函数调用它,如下所示:
template <typename Task, typename Priority>
void Heap<Task, Priority>::bubble_up(const size_t& start_index)
{
....
if (priority_of(start_index) > priority_of((parent_of(start_index))))
{
... do work ...
//call recursively the bubble_up
bubble_up(parent_of(start_index));
}
...
}
Run Code Online (Sandbox Code Playgroud)
问题是,priority_of函数参数index在递归的第二次调用中被破坏或释放:
template <typename Task, typename Priority>
const Priority& Heap<Task, Priority>::priority_of(const size_t& index) const
{
return vec.at(index).second; …Run Code Online (Sandbox Code Playgroud) 为什么我不能std::unique_ptr使用std::move语义(我认为)返回包含 , 的类,如下例所示?我认为 return 会调用 class 的 move ctor A,这将std::move是std::unique_ptr. (我使用的是 GCC 11.2,C++20)
例子:
#include <memory>
class A {
public:
explicit A(std::unique_ptr<int> m): m_(std::move(m)) {}
private:
std::unique_ptr<int> m_;
};
A makit(int num) {
auto m = std::make_unique<int>(num);
return std::move(A(m)); // error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]'x86-64 gcc 11.2 #1
}
int main() {
auto a = makit(42);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我相信解决方案是返回 …
我有一个函数将shared_ptr返回给const对象.返回由operator new返回的指针构造的shared_ptr,但返回该指针会导致编译错误:
Error 3 error C2664: 'std::shared_ptr<_Ty>::shared_ptr(std::nullptr_t)' : cannot convert parameter 1 from 'script::float_data *' to 'std::nullptr_t' c:\xxx\value.cpp 59
Run Code Online (Sandbox Code Playgroud)
以下是导致错误的代码:
shared_ptr< const data > float_data::operator + ( shared_ptr< const data > rhs ) const
{
int rhs_as_int; float rhs_as_float;
switch( rhs->to_numeric( rhs_as_int, rhs_as_float ) )
{
case E_INT:
return new float_data( val + rhs_as_int );
case E_FLOAT:
return new float_data( val + rhs_as_float );
}
}
Run Code Online (Sandbox Code Playgroud)
这些课程是:
class data
{
public:
enum type
{
E_INT,
E_FLOAT,
E_STRING
};
public:
virtual …Run Code Online (Sandbox Code Playgroud) c++ ×10
c++11 ×2
constructor ×2
return ×2
stdmove ×2
constants ×1
gcc ×1
member ×1
memory ×1
nrvo ×1
optimization ×1
shared-ptr ×1
unique-ptr ×1
validation ×1
vector ×1